diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index aade51f819..18d8978152 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -955,14 +955,15 @@ void spu_int_ctrl_t::set(u64 ints) ints &= mask; // notify if at least 1 bit was set - if (ints && ~stat.fetch_or(ints) & ints && !tag.expired()) + if (ints && ~stat.fetch_or(ints) & ints) { - reader_lock rlock(id_manager::g_mutex); + std::shared_lock rlock(id_manager::g_mutex); if (const auto tag_ptr = tag.lock()) { if (auto handler = tag_ptr->handler.lock()) { + rlock.unlock(); handler->exec(); } } diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index be133c0d54..8ae81adc69 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -1690,7 +1690,12 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) sys_spu.warning("sys_raw_spu_destroy(id=%d)", id); - const auto thread = idm::get>(spu_thread::find_raw_spu(id)); + auto thread = idm::get>(spu_thread::find_raw_spu(id), [](named_thread& thread) + { + // Stop thread + thread.state += cpu_flag::exit; + thread = thread_state::aborting; + }); if (!thread) [[unlikely]] { @@ -1699,9 +1704,6 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) // TODO: CELL_EBUSY is not returned - // Stop thread - thread->state += cpu_flag::stop; - // Kernel objects which must be removed std::vector, u32>> to_remove; @@ -1742,7 +1744,7 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) idm::remove_verify(pair.second, std::move(pair.first)); } - if (!idm::remove_verify>(thread->id, std::move(thread))) + if (!idm::remove_verify>(id, std::move(thread))) { // Other thread destroyed beforehead return CELL_ESRCH; @@ -1770,7 +1772,7 @@ error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_i auto thread = idm::check_unlocked>(spu_thread::find_raw_spu(id)); - if (!thread) + if (!thread || *thread == thread_state::aborting) { error = CELL_ESRCH; return result;