1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

Remove SPU and PPU destructors

This commit is contained in:
Eladash 2021-01-19 20:15:57 +02:00 committed by Ivan
parent eb086b0e3f
commit f81674232e
6 changed files with 77 additions and 44 deletions

View File

@ -914,15 +914,6 @@ void ppu_thread::exec_task()
ppu_thread::~ppu_thread() ppu_thread::~ppu_thread()
{ {
// Deallocate Stack Area
ensure(vm::dealloc(stack_addr, vm::stack));
if (const auto dct = g_fxo->get<lv2_memory_container>())
{
dct->used -= stack_size;
}
perf_log.notice("Perf stats for STCX reload: successs %u, failure %u", last_succ, last_fail);
} }
ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u32 prio, int detached) ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u32 prio, int detached)

View File

@ -1675,26 +1675,12 @@ void spu_thread::cpu_task()
} }
} }
spu_thread::~spu_thread() void spu_thread::cleanup()
{ {
{ const u32 addr = group ? SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (id & 0xffffff) : RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index;
vm::writer_lock(0);
for (s32 i = -1; i < 2; i++) // Deallocate local storage
{ ensure(vm::dealloc(addr, vm::spu, &shm));
// Unmap LS mirrors
shm->unmap_critical(ls + (i * SPU_LS_SIZE));
}
}
if (!group)
{
// Deallocate local storage (thread groups are handled in sys_spu.cpp)
ensure(vm::dealloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, vm::spu));
}
// Release LS mirrors area
utils::memory_release(ls - (SPU_LS_SIZE * 2), SPU_LS_SIZE * 5);
// Deallocate RawSPU ID // Deallocate RawSPU ID
if (get_type() >= spu_type::raw) if (get_type() >= spu_type::raw)
@ -1710,14 +1696,28 @@ spu_thread::~spu_thread()
perf_log.notice("Perf stats for PUTLLC reload: successs %u, failure %u", last_succ, last_fail); perf_log.notice("Perf stats for PUTLLC reload: successs %u, failure %u", last_succ, last_fail);
} }
spu_thread::~spu_thread()
{
{
vm::writer_lock lock(0);
for (s32 i = -1; i < 2; i++)
{
// Unmap LS mirrors
shm->unmap_critical(ls + (i * SPU_LS_SIZE));
}
}
// Release LS mirrors area
utils::memory_release(ls - (SPU_LS_SIZE * 2), SPU_LS_SIZE * 5);
}
spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option) spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option)
: cpu_thread(idm::last_id()) : cpu_thread(idm::last_id())
, index(index) , index(index)
, shm(std::make_shared<utils::shm>(SPU_LS_SIZE)) , shm(std::make_shared<utils::shm>(SPU_LS_SIZE))
, ls([&]() , ls([&]()
{ {
const auto addr = static_cast<u8*>(utils::memory_reserve(SPU_LS_SIZE * 5));
if (!group) if (!group)
{ {
ensure(vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm)); ensure(vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm));
@ -1728,7 +1728,9 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u
ensure(vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm, 0x1000)); ensure(vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm, 0x1000));
} }
vm::writer_lock(0); vm::writer_lock lock(0);
const auto addr = static_cast<u8*>(utils::memory_reserve(SPU_LS_SIZE * 5));
for (u32 i = 1; i < 4; i++) for (u32 i = 1; i < 4; i++)
{ {

View File

@ -634,6 +634,7 @@ public:
virtual void cpu_task() override final; virtual void cpu_task() override final;
virtual void cpu_return() override; virtual void cpu_return() override;
virtual ~spu_thread() override; virtual ~spu_thread() override;
void cleanup();
void cpu_init(); void cpu_init();
static const u32 id_base = 0x02000000; // TODO (used to determine thread type) static const u32 id_base = 0x02000000; // TODO (used to determine thread type)

View File

@ -22,18 +22,14 @@ void lv2_int_serv::exec()
thread_ctrl::notify(*thread); thread_ctrl::notify(*thread);
} }
bool interrupt_thread_exit(ppu_thread& ppu) bool ppu_thread_exit(ppu_thread& ppu);
{
ppu.state += cpu_flag::exit;
return false;
}
void lv2_int_serv::join() void lv2_int_serv::join()
{ {
thread->cmd_list thread->cmd_list
({ ({
{ ppu_cmd::ptr_call, 0 }, { ppu_cmd::ptr_call, 0 },
std::bit_cast<u64>(&interrupt_thread_exit) std::bit_cast<u64>(&ppu_thread_exit)
}); });
thread_ctrl::notify(*thread); thread_ctrl::notify(*thread);

View File

@ -2,6 +2,7 @@
#include "sys_ppu_thread.h" #include "sys_ppu_thread.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/perf_meter.hpp"
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
@ -36,6 +37,22 @@ struct ppu_thread_cleaner
} }
}; };
bool ppu_thread_exit(ppu_thread& ppu)
{
ppu.state += cpu_flag::exit + cpu_flag::wait;
// Deallocate Stack Area
ensure(vm::dealloc(ppu.stack_addr, vm::stack) == ppu.stack_size);
if (const auto dct = g_fxo->get<lv2_memory_container>())
{
dct->used -= ppu.stack_size;
}
perf_log.notice("Perf stats for STCX reload: successs %u, failure %u", ppu.last_succ, ppu.last_fail);
return false;
}
void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode) void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
{ {
ppu.state += cpu_flag::wait; ppu.state += cpu_flag::wait;
@ -77,10 +94,15 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
ppu.state -= cpu_flag::suspend; ppu.state -= cpu_flag::suspend;
} }
if (old_status == ppu_join_status::detached) g_fxo->get<ppu_thread_cleaner>()->clean(old_status == ppu_join_status::detached ? ppu.id : 0);
if (old_status == ppu_join_status::joinable)
{ {
g_fxo->get<ppu_thread_cleaner>()->clean(ppu.id); // Wait for termination
ppu.joiner.wait(ppu_join_status::zombie);
} }
ppu_thread_exit(ppu);
} }
s32 sys_ppu_thread_yield(ppu_thread& ppu) s32 sys_ppu_thread_yield(ppu_thread& ppu)
@ -114,7 +136,7 @@ error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr
if (value == ppu_join_status::zombie) if (value == ppu_join_status::zombie)
{ {
value = ppu_join_status::exited; value = ppu_join_status::exited;
return CELL_EBUSY; return CELL_EAGAIN;
} }
if (value == ppu_join_status::exited) if (value == ppu_join_status::exited)
@ -135,6 +157,10 @@ error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr
{ {
lv2_obj::sleep(ppu); lv2_obj::sleep(ppu);
} }
else if (result == CELL_EAGAIN)
{
thread.joiner.notify_one();
}
return result; return result;
}); });
@ -144,7 +170,7 @@ error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr
return CELL_ESRCH; return CELL_ESRCH;
} }
if (thread.ret && thread.ret != CELL_EBUSY) if (thread.ret && thread.ret != CELL_EAGAIN)
{ {
return thread.ret; return thread.ret;
} }
@ -183,7 +209,7 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread) -> CellError const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread) -> CellError
{ {
return thread.joiner.atomic_op([](ppu_join_status& value) -> CellError CellError result = thread.joiner.atomic_op([](ppu_join_status& value) -> CellError
{ {
if (value == ppu_join_status::zombie) if (value == ppu_join_status::zombie)
{ {
@ -209,6 +235,13 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
value = ppu_join_status::detached; value = ppu_join_status::detached;
return {}; return {};
}); });
if (result == CELL_EAGAIN)
{
thread.joiner.notify_one();
}
return result;
}); });
if (!thread) if (!thread)
@ -223,7 +256,8 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
if (thread.ret == CELL_EAGAIN) if (thread.ret == CELL_EAGAIN)
{ {
ensure(idm::remove<named_thread<ppu_thread>>(thread_id)); g_fxo->get<ppu_thread_cleaner>()->clean(thread_id);
g_fxo->get<ppu_thread_cleaner>()->clean(0);
} }
return CELL_OK; return CELL_OK;

View File

@ -687,7 +687,7 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
if (auto thread = t.get()) if (auto thread = t.get())
{ {
// Deallocate LS // Deallocate LS
ensure(vm::get(vm::spu)->dealloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (thread->id & 0xffffff), &thread->shm)); thread->cleanup();
// Remove ID from IDM (destruction will occur in group destructor) // Remove ID from IDM (destruction will occur in group destructor)
idm::remove<named_thread<spu_thread>>(thread->id); idm::remove<named_thread<spu_thread>>(thread->id);
@ -1989,7 +1989,16 @@ error_code raw_spu_destroy(ppu_thread& ppu, u32 id)
(*thread)(); (*thread)();
if (!idm::remove_verify<named_thread<spu_thread>>(idm_id, std::move(thread.ptr))) if (idm::withdraw<named_thread<spu_thread>>(idm_id, [&](spu_thread& spu) -> CellError
{
if (std::addressof(spu) != std::addressof(*thread))
{
return CELL_ESRCH;
}
spu.cleanup();
return {};
}).ret)
{ {
// Other thread destroyed beforehead // Other thread destroyed beforehead
return CELL_ESRCH; return CELL_ESRCH;