mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Make sys_spu_thread_group_join return once per termination
This commit is contained in:
parent
19ff95da70
commit
e3ee481f01
3 changed files with 16 additions and 35 deletions
|
@ -521,6 +521,11 @@ void spu_thread::cpu_stop()
|
||||||
group->stop_count++;
|
group->stop_count++;
|
||||||
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
||||||
|
|
||||||
|
if (!group->join_state)
|
||||||
|
{
|
||||||
|
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
if (const auto ppu = std::exchange(group->waiter, nullptr))
|
if (const auto ppu = std::exchange(group->waiter, nullptr))
|
||||||
{
|
{
|
||||||
// Send exit status directly to the joining thread
|
// Send exit status directly to the joining thread
|
||||||
|
@ -2436,7 +2441,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
}
|
}
|
||||||
|
|
||||||
group->exit_status = value;
|
group->exit_status = value;
|
||||||
group->join_state |= SPU_TGJSF_GROUP_EXIT;
|
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
||||||
|
|
||||||
state += cpu_flag::stop;
|
state += cpu_flag::stop;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -607,7 +607,7 @@ error_code sys_spu_thread_group_terminate(u32 id, s32 value)
|
||||||
}
|
}
|
||||||
|
|
||||||
group->exit_status = value;
|
group->exit_status = value;
|
||||||
group->join_state |= SPU_TGJSF_TERMINATED;
|
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;
|
||||||
|
|
||||||
// Wait until the threads are actually stopped
|
// Wait until the threads are actually stopped
|
||||||
const u64 last_stop = group->stop_count - !group->running;
|
const u64 last_stop = group->stop_count - !group->running;
|
||||||
|
@ -648,11 +648,12 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group->run_state == SPU_THREAD_GROUP_STATUS_INITIALIZED)
|
if (group->join_state)
|
||||||
{
|
{
|
||||||
// Already terminated
|
// Already signaled
|
||||||
ppu.gpr[4] = group->join_state;
|
ppu.gpr[4] = group->join_state;
|
||||||
ppu.gpr[5] = group->exit_status;
|
ppu.gpr[5] = group->exit_status;
|
||||||
|
group->join_state.release(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -661,11 +662,9 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
group->waiter = &ppu;
|
group->waiter = &ppu;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 last_stop = group->stop_count - !group->running;
|
|
||||||
|
|
||||||
lv2_obj::sleep(ppu);
|
lv2_obj::sleep(ppu);
|
||||||
|
|
||||||
while (group->stop_count == last_stop)
|
while (!group->join_state)
|
||||||
{
|
{
|
||||||
if (ppu.is_stopped())
|
if (ppu.is_stopped())
|
||||||
{
|
{
|
||||||
|
@ -674,6 +673,8 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
|
|
||||||
group->cond.wait(lock);
|
group->cond.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group->join_state.release(0);
|
||||||
}
|
}
|
||||||
while (0);
|
while (0);
|
||||||
|
|
||||||
|
@ -682,27 +683,9 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ppu.gpr[4] & (SPU_TGJSF_GROUP_EXIT | SPU_TGJSF_TERMINATED))
|
if (cause)
|
||||||
{
|
{
|
||||||
case 0:
|
*cause = static_cast<u32>(ppu.gpr[4]);
|
||||||
{
|
|
||||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SPU_TGJSF_GROUP_EXIT:
|
|
||||||
{
|
|
||||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SPU_TGJSF_TERMINATED:
|
|
||||||
{
|
|
||||||
if (cause) *cause = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
fmt::throw_exception("Unexpected join_state" HERE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
|
|
|
@ -207,13 +207,6 @@ enum : u32
|
||||||
SYS_SPU_IMAGE_DIRECT = 1,
|
SYS_SPU_IMAGE_DIRECT = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// SPU Thread Group Join State Flag
|
|
||||||
enum : u32
|
|
||||||
{
|
|
||||||
SPU_TGJSF_TERMINATED = (1 << 1), // set if SPU Thread Group is terminated by sys_spu_thread_group_terminate
|
|
||||||
SPU_TGJSF_GROUP_EXIT = (1 << 2), // set if SPU Thread Group is terminated by sys_spu_thread_group_exit
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lv2_spu_group
|
struct lv2_spu_group
|
||||||
{
|
{
|
||||||
static const u32 id_base = 1; // Wrong?
|
static const u32 id_base = 1; // Wrong?
|
||||||
|
@ -232,7 +225,7 @@ struct lv2_spu_group
|
||||||
atomic_t<s32> prio; // SPU Thread Group Priority
|
atomic_t<s32> prio; // SPU Thread Group Priority
|
||||||
atomic_t<u32> run_state; // SPU Thread Group State
|
atomic_t<u32> run_state; // SPU Thread Group State
|
||||||
atomic_t<s32> exit_status; // SPU Thread Group Exit Status
|
atomic_t<s32> exit_status; // SPU Thread Group Exit Status
|
||||||
atomic_t<u32> join_state; // flags used to detect exit cause
|
atomic_t<u32> join_state; // flags used to detect exit cause and signal
|
||||||
atomic_t<u32> running; // Number of running threads
|
atomic_t<u32> running; // Number of running threads
|
||||||
cond_variable cond; // used to signal waiting PPU thread
|
cond_variable cond; // used to signal waiting PPU thread
|
||||||
atomic_t<u64> stop_count;
|
atomic_t<u64> stop_count;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue