mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
sys_spu: Improve sys_spu_thread_get_exit_status
This commit is contained in:
parent
14969cd8d0
commit
09797c3584
4 changed files with 46 additions and 14 deletions
|
@ -991,6 +991,12 @@ void spu_thread::cpu_stop()
|
|||
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
|
||||
}
|
||||
|
||||
if (status_npc.load().status >> 16 == SYS_SPU_THREAD_STOP_THREAD_EXIT)
|
||||
{
|
||||
// Set exit status now, in conjunction with group state changes
|
||||
exit_status.set_value(last_exit_status);
|
||||
}
|
||||
|
||||
if (const auto ppu = std::exchange(group->waiter, nullptr))
|
||||
{
|
||||
// Send exit status directly to the joining thread
|
||||
|
@ -1003,6 +1009,10 @@ void spu_thread::cpu_stop()
|
|||
// Notify on last thread stopped
|
||||
group->cond.notify_all();
|
||||
}
|
||||
else if (status_npc.load().status >> 16 == SYS_SPU_THREAD_STOP_THREAD_EXIT)
|
||||
{
|
||||
exit_status.set_value(last_exit_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2737,10 +2747,8 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
{
|
||||
spu_log.trace("stop_and_signal(code=0x%x)", code);
|
||||
|
||||
if (offset >= RAW_SPU_BASE_ADDR)
|
||||
auto set_status_npc = [&]()
|
||||
{
|
||||
// Save next PC and current SPU Interrupt Status
|
||||
state += cpu_flag::stop + cpu_flag::wait;
|
||||
status_npc.atomic_op([&](status_npc_sync_var& state)
|
||||
{
|
||||
state.status = (state.status & 0xffff) | (code << 16);
|
||||
|
@ -2748,6 +2756,13 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
state.status &= ~SPU_STATUS_RUNNING;
|
||||
state.npc = (pc + 4) | +interrupts_enabled;
|
||||
});
|
||||
};
|
||||
|
||||
if (offset >= RAW_SPU_BASE_ADDR)
|
||||
{
|
||||
// Save next PC and current SPU Interrupt Status
|
||||
state += cpu_flag::stop + cpu_flag::wait;
|
||||
set_status_npc();
|
||||
|
||||
status_npc.notify_one();
|
||||
|
||||
|
@ -2810,7 +2825,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
return true;
|
||||
}
|
||||
|
||||
case 0x110:
|
||||
case SYS_SPU_THREAD_STOP_RECEIVE_EVENT:
|
||||
{
|
||||
/* ===== sys_spu_thread_receive_event ===== */
|
||||
|
||||
|
@ -2977,7 +2992,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
return true;
|
||||
}
|
||||
|
||||
case 0x111:
|
||||
case SYS_SPU_THREAD_STOP_TRY_RECEIVE_EVENT:
|
||||
{
|
||||
/* ===== sys_spu_thread_tryreceive_event ===== */
|
||||
|
||||
|
@ -3037,7 +3052,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
return true;
|
||||
}
|
||||
|
||||
case 0x100:
|
||||
case SYS_SPU_THREAD_STOP_YIELD:
|
||||
{
|
||||
// SPU thread group yield (TODO)
|
||||
if (ch_out_mbox.get_count())
|
||||
|
@ -3049,7 +3064,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
return true;
|
||||
}
|
||||
|
||||
case 0x101:
|
||||
case SYS_SPU_THREAD_STOP_GROUP_EXIT:
|
||||
{
|
||||
/* ===== sys_spu_thread_group_exit ===== */
|
||||
|
||||
|
@ -3098,6 +3113,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
|
||||
group->exit_status = value;
|
||||
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
||||
set_status_npc();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3106,7 +3122,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
return true;
|
||||
}
|
||||
|
||||
case 0x102:
|
||||
case SYS_SPU_THREAD_STOP_THREAD_EXIT:
|
||||
{
|
||||
/* ===== sys_spu_thread_exit ===== */
|
||||
|
||||
|
@ -3117,8 +3133,10 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
fmt::throw_exception("sys_spu_thread_exit(): Out_MBox is empty" HERE);
|
||||
}
|
||||
|
||||
spu_log.trace("sys_spu_thread_exit(status=0x%x)", ch_out_mbox.get_value());
|
||||
status_npc = {SPU_STATUS_STOPPED_BY_STOP, 0};
|
||||
const u32 value = ch_out_mbox.get_value();
|
||||
spu_log.trace("sys_spu_thread_exit(status=0x%x)", value);
|
||||
last_exit_status = value;
|
||||
set_status_npc();
|
||||
state += cpu_flag::stop;
|
||||
check_state();
|
||||
return true;
|
||||
|
|
|
@ -599,6 +599,8 @@ public:
|
|||
|
||||
std::array<std::pair<u32, std::weak_ptr<lv2_event_queue>>, 32> spuq; // Event Queue Keys for SPU Thread
|
||||
std::weak_ptr<lv2_event_queue> spup[64]; // SPU Ports
|
||||
spu_channel exit_status{}; // Threaded SPU exit status (not a channel, but the interface fits)
|
||||
u32 last_exit_status; // Value to be written in exit_status after checking group termination
|
||||
|
||||
const u32 index; // SPU index
|
||||
const u32 offset; // SPU LS offset
|
||||
|
|
|
@ -453,7 +453,7 @@ error_code sys_spu_thread_set_argument(ppu_thread& ppu, u32 id, vm::ptr<sys_spu_
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr<u32> status)
|
||||
error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr<s32> status)
|
||||
{
|
||||
vm::temporary_unlock(ppu);
|
||||
|
||||
|
@ -466,9 +466,11 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr<u32>
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (thread->status_npc.load().status & SPU_STATUS_STOPPED_BY_STOP)
|
||||
const u64 exit_status = thread->exit_status.data.load();
|
||||
|
||||
if (exit_status & spu_channel::bit_count)
|
||||
{
|
||||
*status = thread->ch_out_mbox.get_value();
|
||||
*status = static_cast<s32>(exit_status);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,16 @@ enum : s32
|
|||
SYS_SPU_SEGMENT_TYPE_INFO = 4,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
SYS_SPU_THREAD_STOP_YIELD = 0x0100,
|
||||
SYS_SPU_THREAD_STOP_GROUP_EXIT = 0x0101,
|
||||
SYS_SPU_THREAD_STOP_THREAD_EXIT = 0x0102,
|
||||
SYS_SPU_THREAD_STOP_RECEIVE_EVENT = 0x0110,
|
||||
SYS_SPU_THREAD_STOP_TRY_RECEIVE_EVENT = 0x0111,
|
||||
SYS_SPU_THREAD_STOP_SWITCH_SYSTEM_MODULE = 0x0120,
|
||||
};
|
||||
|
||||
struct sys_spu_thread_group_attribute
|
||||
{
|
||||
be_t<u32> nsize; // name length including NULL terminator
|
||||
|
@ -367,7 +377,7 @@ error_code sys_spu_thread_connect_event(ppu_thread&, u32 id, u32 eq, u32 et, u8
|
|||
error_code sys_spu_thread_disconnect_event(ppu_thread&, u32 id, u32 event_type, u8 spup);
|
||||
error_code sys_spu_thread_bind_queue(ppu_thread&, u32 id, u32 spuq, u32 spuq_num);
|
||||
error_code sys_spu_thread_unbind_queue(ppu_thread&, u32 id, u32 spuq_num);
|
||||
error_code sys_spu_thread_get_exit_status(ppu_thread&, u32 id, vm::ptr<u32> status);
|
||||
error_code sys_spu_thread_get_exit_status(ppu_thread&, u32 id, vm::ptr<s32> status);
|
||||
error_code sys_spu_thread_recover_page_fault(ppu_thread&, u32 id);
|
||||
|
||||
error_code sys_raw_spu_create(ppu_thread&, vm::ptr<u32> id, vm::ptr<void> attr);
|
||||
|
|
Loading…
Add table
Reference in a new issue