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()
{
// 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)

View File

@ -1675,26 +1675,12 @@ void spu_thread::cpu_task()
}
}
spu_thread::~spu_thread()
void spu_thread::cleanup()
{
{
vm::writer_lock(0);
const u32 addr = group ? SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (id & 0xffffff) : RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index;
for (s32 i = -1; i < 2; i++)
{
// 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 local storage
ensure(vm::dealloc(addr, vm::spu, &shm));
// Deallocate RawSPU ID
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);
}
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)
: cpu_thread(idm::last_id())
, index(index)
, shm(std::make_shared<utils::shm>(SPU_LS_SIZE))
, ls([&]()
{
const auto addr = static_cast<u8*>(utils::memory_reserve(SPU_LS_SIZE * 5));
if (!group)
{
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));
}
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++)
{

View File

@ -634,6 +634,7 @@ public:
virtual void cpu_task() override final;
virtual void cpu_return() override;
virtual ~spu_thread() override;
void cleanup();
void cpu_init();
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);
}
bool interrupt_thread_exit(ppu_thread& ppu)
{
ppu.state += cpu_flag::exit;
return false;
}
bool ppu_thread_exit(ppu_thread& ppu);
void lv2_int_serv::join()
{
thread->cmd_list
({
{ ppu_cmd::ptr_call, 0 },
std::bit_cast<u64>(&interrupt_thread_exit)
std::bit_cast<u64>(&ppu_thread_exit)
});
thread_ctrl::notify(*thread);

View File

@ -2,6 +2,7 @@
#include "sys_ppu_thread.h"
#include "Emu/IdManager.h"
#include "Emu/perf_meter.hpp"
#include "Emu/Cell/ErrorCodes.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)
{
ppu.state += cpu_flag::wait;
@ -77,10 +94,15 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
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)
@ -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)
{
value = ppu_join_status::exited;
return CELL_EBUSY;
return CELL_EAGAIN;
}
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);
}
else if (result == CELL_EAGAIN)
{
thread.joiner.notify_one();
}
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;
}
if (thread.ret && thread.ret != CELL_EBUSY)
if (thread.ret && thread.ret != CELL_EAGAIN)
{
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
{
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)
{
@ -209,6 +235,13 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
value = ppu_join_status::detached;
return {};
});
if (result == CELL_EAGAIN)
{
thread.joiner.notify_one();
}
return result;
});
if (!thread)
@ -223,7 +256,8 @@ error_code sys_ppu_thread_detach(ppu_thread& ppu, u32 thread_id)
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;

View File

@ -687,7 +687,7 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
if (auto thread = t.get())
{
// 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)
idm::remove<named_thread<spu_thread>>(thread->id);
@ -1989,7 +1989,16 @@ error_code raw_spu_destroy(ppu_thread& ppu, u32 id)
(*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
return CELL_ESRCH;