diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index d6e947707e..279530619f 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -155,7 +155,7 @@ bool RawSPUThread::WriteReg(const u32 addr, const u32 value) if (value) { - int2.set(SPU_INT2_STAT_DMA_TAG_GROUP_COMPLETION_INT); // TODO + int_ctrl[2].set(SPU_INT2_STAT_DMA_TAG_GROUP_COMPLETION_INT); // TODO } return true; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index bb82448f41..10365bcff6 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -10,6 +10,7 @@ #include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/lv2/sys_event_flag.h" #include "Emu/SysCalls/lv2/sys_event.h" +#include "Emu/SysCalls/lv2/sys_interrupt.h" #include "Emu/Cell/SPUDisAsm.h" #include "Emu/Cell/SPUThread.h" @@ -22,6 +23,30 @@ extern u64 get_timebased_time(); +void spu_int_ctrl_t::set(u64 ints) +{ + // leave only enabled interrupts + ints &= mask.load(); + + // notify if at least 1 bit was set + if (ints && ~stat._or(ints) & ints && tag) + { + LV2_LOCK; + + if (tag && tag->handler) + { + tag->handler->signal++; + + tag->handler->thread->cv.notify_one(); + } + } +} + +void spu_int_ctrl_t::clear(u64 ints) +{ + stat &= ~ints; +} + const g_spu_imm_table_t g_spu_imm; class spu_inter_func_list_t @@ -193,8 +218,7 @@ void SPUThread::InitRegs() status = {}; npc = {}; - int0.clear(); - int2.clear(); + int_ctrl = {}; GPR[1]._u32[3] = 0x3FFF0; // initial stack frame pointer } @@ -572,7 +596,7 @@ u32 SPUThread::get_ch_value(u32 ch) if (count + 1 == 4 /* SPU_IN_MBOX_THRESHOLD */) // TODO: check this { - int2.set(SPU_INT2_STAT_SPU_MAILBOX_THRESHOLD_INT); + int_ctrl[2].set(SPU_INT2_STAT_SPU_MAILBOX_THRESHOLD_INT); } return result; @@ -684,7 +708,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value) cv.wait_for(lock, std::chrono::milliseconds(1)); } - int2.set(SPU_INT2_STAT_MAILBOX_INT); + int_ctrl[2].set(SPU_INT2_STAT_MAILBOX_INT); return; } else @@ -1030,7 +1054,7 @@ void SPUThread::stop_and_signal(u32 code) status &= ~SPU_STATUS_RUNNING; }); - int2.set(SPU_INT2_STAT_SPU_STOP_AND_SIGNAL_INT); + int_ctrl[2].set(SPU_INT2_STAT_SPU_STOP_AND_SIGNAL_INT); return Stop(); } @@ -1295,7 +1319,7 @@ void SPUThread::halt() status &= ~SPU_STATUS_RUNNING; }); - int2.set(SPU_INT2_STAT_SPU_HALT_OR_STEP_INT); + int_ctrl[2].set(SPU_INT2_STAT_SPU_HALT_OR_STEP_INT); return Stop(); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 48f4128eda..f4697ccc6a 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -6,6 +6,7 @@ struct lv2_event_queue_t; struct spu_group_t; +struct lv2_int_tag_t; // SPU Channels enum : u32 @@ -276,41 +277,16 @@ public: } }; -struct spu_interrupt_tag_t +struct spu_int_ctrl_t { atomic_t mask; atomic_t stat; - atomic_t assigned; + std::shared_ptr tag; - std::mutex handler_mutex; - std::condition_variable cond; + void set(u64 ints); -public: - void set(u64 ints) - { - // leave only enabled interrupts - ints &= mask.load(); - - if (ints && ~stat._or(ints) & ints) - { - // notify if at least 1 bit was set - cond.notify_all(); - } - } - - void clear(u64 ints) - { - stat &= ~ints; - } - - void clear() - { - mask = {}; - stat = {}; - - assigned = { -1 }; - } + void clear(u64 ints); }; struct g_spu_imm_table_t @@ -533,8 +509,7 @@ public: atomic_t status; // SPU Status register atomic_t npc; // SPU Next Program Counter register - spu_interrupt_tag_t int0; // SPU Class 0 Interrupt Management - spu_interrupt_tag_t int2; // SPU Class 2 Interrupt Management + std::array int_ctrl; // SPU Class 0, 1, 2 Interrupt Management std::weak_ptr tg; // SPU Thread Group diff --git a/rpcs3/Emu/SysCalls/FuncList.cpp b/rpcs3/Emu/SysCalls/FuncList.cpp index 90d8bfdcc0..359ee63438 100644 --- a/rpcs3/Emu/SysCalls/FuncList.cpp +++ b/rpcs3/Emu/SysCalls/FuncList.cpp @@ -63,7 +63,7 @@ std::string SysCalls::GetFuncName(const u64 fid) case 81: return "sys_interrupt_tag_destroy"; case 82: return "sys_event_flag_create"; case 83: return "sys_event_flag_destroy"; - case 84: return "sys_interrupt_thread_establish"; + case 84: return "_sys_interrupt_thread_establish"; case 85: return "sys_event_flag_wait"; case 86: return "sys_event_flag_trywait"; case 87: return "sys_event_flag_set"; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 8e7c843e4a..d4896ae5a5 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -823,7 +823,7 @@ s32 sys_interrupt_thread_disestablish(PPUThread& CPU, u32 ih) { sysPrxForUser.Todo("sys_interrupt_thread_disestablish(ih=0x%x)", ih); - return _sys_interrupt_thread_disestablish(ih, vm::stackvar>(CPU)); + return _sys_interrupt_thread_disestablish(CPU, ih, vm::stackvar>(CPU)); } s32 sys_process_is_stack(u32 p) diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 954068371f..1e8aed17d9 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -124,7 +124,7 @@ const ppu_func_caller g_sc_table[1024] = bind_func(sys_interrupt_tag_destroy), //81 (0x051) bind_func(sys_event_flag_create), //82 (0x052) bind_func(sys_event_flag_destroy), //83 (0x053) - bind_func(sys_interrupt_thread_establish), //84 (0x054) + bind_func(_sys_interrupt_thread_establish), //84 (0x054) bind_func(sys_event_flag_wait), //85 (0x055) bind_func(sys_event_flag_trywait), //86 (0x056) bind_func(sys_event_flag_set), //87 (0x057) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index 902d45cfc7..8e19e0e2aa 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -102,7 +102,7 @@ struct lv2_event_queue_t lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 key, s32 size); - void push(lv2_lock_type& lv2_lock, u64 source, u64 data1, u64 data2, u64 data3) + void push(lv2_lock_t& lv2_lock, u64 source, u64 data1, u64 data2, u64 data3) { CHECK_LV2_LOCK(lv2_lock); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp index 6792fcbc30..9f11f95e34 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp @@ -3,70 +3,83 @@ #include "Emu/System.h" #include "Emu/IdManager.h" #include "Emu/SysCalls/SysCalls.h" -#include "Emu/SysCalls/CB_FUNC.h" -#include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" -#include "Emu/Cell/RawSPUThread.h" #include "sys_interrupt.h" SysCallBase sys_interrupt("sys_interrupt"); +lv2_int_tag_t::lv2_int_tag_t() + : id(Emu.GetIdManager().get_current_id()) +{ +} + +lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr& thread) + : thread(thread) + , id(Emu.GetIdManager().get_current_id()) +{ +} + +void lv2_int_serv_t::join(PPUThread& ppu, lv2_lock_t& lv2_lock) +{ + CHECK_LV2_LOCK(lv2_lock); + + // Use is_joining to stop interrupt thread and signal + thread->is_joining = true; + + thread->cv.notify_one(); + + // Start joining + while (thread->IsActive()) + { + CHECK_EMU_STATUS; + + ppu.cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); + } + + // Cleanup + Emu.GetIdManager().remove(id); + Emu.GetIdManager().remove(thread->GetId()); +} + s32 sys_interrupt_tag_destroy(u32 intrtag) { sys_interrupt.Warning("sys_interrupt_tag_destroy(intrtag=0x%x)", intrtag); - const u32 class_id = intrtag >> 8; + LV2_LOCK; - if (class_id != 0 && class_id != 2) + const auto tag = Emu.GetIdManager().get(intrtag); + + if (!tag) { return CELL_ESRCH; } - const auto thread = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff); - - if (!thread) + if (tag->handler) { - return CELL_ESRCH; + return CELL_EBUSY; } - auto& tag = class_id ? thread->int2 : thread->int0; - - if (s32 old = tag.assigned.compare_and_swap(0, -1)) - { - if (old > 0) - { - return CELL_EBUSY; - } - - return CELL_ESRCH; - } + Emu.GetIdManager().remove(intrtag); return CELL_OK; } -s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread, u64 arg) +s32 _sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread, u64 arg1, u64 arg2) { - sys_interrupt.Warning("sys_interrupt_thread_establish(ih=*0x%x, intrtag=0x%x, intrthread=0x%x, arg=0x%llx)", ih, intrtag, intrthread, arg); + sys_interrupt.Warning("_sys_interrupt_thread_establish(ih=*0x%x, intrtag=0x%x, intrthread=0x%x, arg1=0x%llx, arg2=0x%llx)", ih, intrtag, intrthread, arg1, arg2); - const u32 class_id = intrtag >> 8; + LV2_LOCK; - if (class_id != 0 && class_id != 2) + // Get interrupt tag + const auto tag = Emu.GetIdManager().get(intrtag); + + if (!tag) { return CELL_ESRCH; } - const auto thread = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff); - - if (!thread) - { - return CELL_ESRCH; - } - - auto& tag = class_id ? thread->int2 : thread->int0; - - // CELL_ESTAT is not returned (can't detect exact condition) - + // Get interrupt thread const auto it = Emu.GetIdManager().get(intrthread); if (!it) @@ -74,82 +87,95 @@ s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread, return CELL_ESRCH; } + // If interrupt thread is running, it's already established on another interrupt tag + if (!it->IsStopped()) { - LV2_LOCK; - - if (it->custom_task) - { - return CELL_EAGAIN; - } - - if (s32 res = tag.assigned.atomic_op([](s32& value) -> s32 - { - if (value < 0) - { - return CELL_ESRCH; - } - - value++; - return CELL_OK; - })) - { - return res; - } - - it->custom_task = [thread, &tag, arg](PPUThread& CPU) - { - const u32 pc = CPU.PC; - const u32 rtoc = CPU.GPR[2]; - - std::unique_lock lock(tag.handler_mutex); - - while (!CPU.IsStopped()) - { - CHECK_EMU_STATUS; - - // call interrupt handler until int status is clear - if (tag.stat.load()) - { - CPU.GPR[3] = arg; - CPU.FastCall2(pc, rtoc); - } - - tag.cond.wait_for(lock, std::chrono::milliseconds(1)); - } - }; + return CELL_EAGAIN; } - *ih = Emu.GetIdManager().make(it); + // It's unclear if multiple handlers can be established on single interrupt tag + if (tag->handler) + { + sys_interrupt.Error("_sys_interrupt_thread_establish(): handler service already exists (intrtag=0x%x) -> CELL_ESTAT", intrtag); + return CELL_ESTAT; + } + + const auto handler = Emu.GetIdManager().make_ptr(it); + + tag->handler = handler; + + it->custom_task = [handler, arg1, arg2](PPUThread& ppu) + { + const u32 pc = ppu.PC; + const u32 rtoc = ppu.GPR[2]; + + LV2_LOCK; + + while (!ppu.is_joining) + { + CHECK_EMU_STATUS; + + // call interrupt handler until int status is clear + if (handler->signal) + { + if (lv2_lock) lv2_lock.unlock(); + + ppu.GPR[3] = arg1; + ppu.GPR[4] = arg2; + ppu.FastCall2(pc, rtoc); + + handler->signal--; + continue; + } + + if (!lv2_lock) + { + lv2_lock.lock(); + continue; + } + + ppu.cv.wait(lv2_lock); + } + + ppu.Exit(); + }; + it->Exec(); + *ih = handler->id; + return CELL_OK; } -s32 _sys_interrupt_thread_disestablish(u32 ih, vm::ptr r13) +s32 _sys_interrupt_thread_disestablish(PPUThread& ppu, u32 ih, vm::ptr r13) { - sys_interrupt.Todo("_sys_interrupt_thread_disestablish(ih=0x%x, r13=*0x%x)", ih, r13); + sys_interrupt.Warning("_sys_interrupt_thread_disestablish(ih=0x%x, r13=*0x%x)", ih, r13); - const auto handler = Emu.GetIdManager().get(ih); + LV2_LOCK; + + const auto handler = Emu.GetIdManager().get(ih); if (!handler) { return CELL_ESRCH; } - // TODO: wait for sys_interrupt_thread_eoi() and destroy interrupt thread + // Wait for sys_interrupt_thread_eoi() and destroy interrupt thread + handler->join(ppu, lv2_lock); + // Save TLS base *r13 = handler->thread->GPR[13]; return CELL_OK; } -void sys_interrupt_thread_eoi(PPUThread& CPU) +void sys_interrupt_thread_eoi(PPUThread& ppu) { sys_interrupt.Log("sys_interrupt_thread_eoi()"); // TODO: maybe it should actually unwind the stack of PPU thread? - CPU.GPR[1] = align(CPU.stack_addr + CPU.stack_size, 0x200) - 0x200; // supercrutch to bypass stack check + ppu.GPR[1] = align(ppu.stack_addr + ppu.stack_size, 0x200) - 0x200; // supercrutch to bypass stack check - CPU.FastStop(); + ppu.FastStop(); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h index 2a34aa42fd..16af8b9c5e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.h @@ -4,20 +4,36 @@ namespace vm { using namespace ps3; } class PPUThread; -struct lv2_int_handler_t +struct lv2_int_tag_t { - const std::shared_ptr thread; + //const u32 class_id; // 0 or 2 for RawSPU + const u32 id; - lv2_int_handler_t(const std::shared_ptr& thread) - : thread(thread) - { - } + //const std::weak_ptr thread; // RawSPU thread + + std::shared_ptr handler; + + lv2_int_tag_t(/*u32 class_id, const std::shared_ptr thread*/); }; -REG_ID_TYPE(lv2_int_handler_t, 0x0B); // SYS_INTR_SERVICE_HANDLE_OBJECT +REG_ID_TYPE(lv2_int_tag_t, 0x0A); // SYS_INTR_TAG_OBJECT + +struct lv2_int_serv_t +{ + const std::shared_ptr thread; + const u32 id; + + std::atomic signal{ 0 }; // signal count + + lv2_int_serv_t(const std::shared_ptr& thread); + + void join(PPUThread& ppu, lv2_lock_t& lv2_lock); +}; + +REG_ID_TYPE(lv2_int_serv_t, 0x0B); // SYS_INTR_SERVICE_HANDLE_OBJECT // SysCalls s32 sys_interrupt_tag_destroy(u32 intrtag); -s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread, u64 arg); -s32 _sys_interrupt_thread_disestablish(u32 ih, vm::ptr r13); -void sys_interrupt_thread_eoi(PPUThread& CPU); +s32 _sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u32 intrthread, u64 arg1, u64 arg2); +s32 _sys_interrupt_thread_disestablish(PPUThread& ppu, u32 ih, vm::ptr r13); +void sys_interrupt_thread_eoi(PPUThread& ppu); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index 9946e1a0af..012a970776 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -11,7 +11,7 @@ SysCallBase sys_mutex("sys_mutex"); extern u64 get_system_time(); -void lv2_mutex_t::unlock(lv2_lock_type& lv2_lock) +void lv2_mutex_t::unlock(lv2_lock_t& lv2_lock) { CHECK_LV2_LOCK(lv2_lock); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index d1d7449102..0b88e680bf 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -40,7 +40,7 @@ struct lv2_mutex_t { } - void unlock(lv2_lock_type& lv2_lock); + void unlock(lv2_lock_t& lv2_lock); }; REG_ID_TYPE(lv2_mutex_t, 0x85); // SYS_MUTEX_OBJECT diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 4a7b53fc8e..2ffe44ecbc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -10,6 +10,7 @@ #include "Emu/FS/vfsFile.h" #include "Loader/ELF32.h" #include "Crypto/unself.h" +#include "sys_interrupt.h" #include "sys_event.h" #include "sys_spu.h" @@ -609,7 +610,7 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) throw EXCEPTION("Invalid SPU thread group"); } - if ((group->state < SPU_THREAD_GROUP_STATUS_WAITING) || (group->state > SPU_THREAD_GROUP_STATUS_RUNNING)) + if (group->state < SPU_THREAD_GROUP_STATUS_WAITING || group->state > SPU_THREAD_GROUP_STATUS_RUNNING) { return CELL_ESTAT; } @@ -651,7 +652,7 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr value, u32 type) throw EXCEPTION("Invalid SPU thread group"); } - if ((group->state < SPU_THREAD_GROUP_STATUS_WAITING) || (group->state > SPU_THREAD_GROUP_STATUS_RUNNING)) + if (group->state < SPU_THREAD_GROUP_STATUS_WAITING || group->state > SPU_THREAD_GROUP_STATUS_RUNNING) { return CELL_ESTAT; } @@ -688,7 +689,7 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value) throw EXCEPTION("Invalid SPU thread group"); } - if ((group->state < SPU_THREAD_GROUP_STATUS_WAITING) || (group->state > SPU_THREAD_GROUP_STATUS_RUNNING)) + if (group->state < SPU_THREAD_GROUP_STATUS_WAITING || group->state > SPU_THREAD_GROUP_STATUS_RUNNING) { return CELL_ESTAT; } @@ -765,7 +766,7 @@ s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value) throw EXCEPTION("Invalid SPU thread group"); } - //if ((group->state < SPU_THREAD_GROUP_STATUS_WAITING) || (group->state > SPU_THREAD_GROUP_STATUS_RUNNING)) // ??? + //if (group->state < SPU_THREAD_GROUP_STATUS_WAITING || group->state > SPU_THREAD_GROUP_STATUS_RUNNING) // ??? //{ // return CELL_ESTAT; //} @@ -1149,7 +1150,7 @@ s32 sys_raw_spu_create(vm::ptr id, vm::ptr attr) return CELL_OK; } -s32 sys_raw_spu_destroy(u32 id) +s32 sys_raw_spu_destroy(PPUThread& ppu, u32 id) { sys_spu.Warning("sys_raw_spu_destroy(id=%d)", id); @@ -1162,7 +1163,24 @@ s32 sys_raw_spu_destroy(u32 id) return CELL_ESRCH; } - // TODO: check if busy + // TODO: CELL_EBUSY is not returned + + // Stop thread + thread->Stop(); + + // Clear interrupt handlers + for (auto& intr : thread->int_ctrl) + { + if (intr.tag) + { + if (intr.tag->handler) + { + intr.tag->handler->join(ppu, lv2_lock); + } + + Emu.GetIdManager().remove(intr.tag->id); + } + } Emu.GetIdManager().remove(thread->GetId()); @@ -1173,10 +1191,7 @@ s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr { sys_spu.Warning("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag=*0x%x)", id, class_id, hwthread, intrtag); - if (class_id != 0 && class_id != 2) - { - return CELL_EINVAL; - } + LV2_LOCK; const auto thread = Emu.GetCPU().GetRawSPUThread(id); @@ -1185,14 +1200,21 @@ s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr return CELL_ESRCH; } - auto& tag = class_id ? thread->int2 : thread->int0; + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } - if (!tag.assigned.compare_and_swap_test(-1, 0)) + auto& int_ctrl = thread->int_ctrl[class_id]; + + if (int_ctrl.tag) { return CELL_EAGAIN; } - *intrtag = (id & 0xff) | (class_id << 8); + int_ctrl.tag = Emu.GetIdManager().make_ptr(); + + *intrtag = int_ctrl.tag->id; return CELL_OK; } @@ -1213,9 +1235,7 @@ s32 sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask) return CELL_ESRCH; } - auto& tag = class_id ? thread->int2 : thread->int0; - - tag.mask.exchange(mask); + thread->int_ctrl[class_id].mask.exchange(mask); return CELL_OK; } @@ -1236,9 +1256,7 @@ s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ptr mask) return CELL_ESRCH; } - auto& tag = class_id ? thread->int2 : thread->int0; - - *mask = tag.mask.load(); + *mask = thread->int_ctrl[class_id].mask.load(); return CELL_OK; } @@ -1259,9 +1277,7 @@ s32 sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat) return CELL_ESRCH; } - auto& tag = class_id ? thread->int2 : thread->int0; - - tag.clear(stat); + thread->int_ctrl[class_id].clear(stat); return CELL_OK; } @@ -1282,9 +1298,7 @@ s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr stat) return CELL_ESRCH; } - auto& tag = class_id ? thread->int2 : thread->int0; - - *stat = tag.stat.load(); + *stat = thread->int_ctrl[class_id].stat.load(); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 6d39a1f8e9..213f2afc0c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -177,7 +177,7 @@ struct spu_group_t { } - void send_run_event(lv2_lock_type& lv2_lock, u64 data1, u64 data2, u64 data3) + void send_run_event(lv2_lock_t& lv2_lock, u64 data1, u64 data2, u64 data3) { CHECK_LV2_LOCK(lv2_lock); @@ -187,7 +187,7 @@ struct spu_group_t } } - void send_exception_event(lv2_lock_type& lv2_lock, u64 data1, u64 data2, u64 data3) + void send_exception_event(lv2_lock_t& lv2_lock, u64 data1, u64 data2, u64 data3) { CHECK_LV2_LOCK(lv2_lock); @@ -197,7 +197,7 @@ struct spu_group_t } } - void send_sysmodule_event(lv2_lock_type& lv2_lock, u64 data1, u64 data2, u64 data3) + void send_sysmodule_event(lv2_lock_t& lv2_lock, u64 data1, u64 data2, u64 data3) { CHECK_LV2_LOCK(lv2_lock); @@ -209,6 +209,7 @@ struct spu_group_t }; struct vfsStream; +class PPUThread; void LoadSpuImage(vfsStream& stream, u32& spu_ep, u32 addr); u32 LoadSpuImage(vfsStream& stream, u32& spu_ep); @@ -247,7 +248,7 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num); s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr status); s32 sys_raw_spu_create(vm::ptr id, vm::ptr attr); -s32 sys_raw_spu_destroy(u32 id); +s32 sys_raw_spu_destroy(PPUThread& ppu, u32 id); s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag); s32 sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask); s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ptr mask); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 308790b69d..d4228ea8af 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -200,10 +200,10 @@ public: force_inline bool IsReady() const { return m_status == Ready; } }; -using lv2_lock_type = std::unique_lock; +using lv2_lock_t = std::unique_lock; -#define LV2_LOCK lv2_lock_type lv2_lock(Emu.GetCoreMutex()) -#define LV2_DEFER_LOCK lv2_lock_type lv2_lock +#define LV2_LOCK lv2_lock_t lv2_lock(Emu.GetCoreMutex()) +#define LV2_DEFER_LOCK lv2_lock_t lv2_lock #define CHECK_LV2_LOCK(x) if (!(x).owns_lock() || (x).mutex() != &Emu.GetCoreMutex()) throw EXCEPTION("Invalid LV2_LOCK (locked=%d)", (x).owns_lock()) #define CHECK_EMU_STATUS if (Emu.IsStopped()) throw EXCEPTION("Aborted (emulation stopped)")