Various changes

This commit is contained in:
Nekotekina 2015-04-12 04:36:25 +03:00
parent d1fbccc9ce
commit ea5110cec3
23 changed files with 483 additions and 403 deletions

View File

@ -64,7 +64,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pAr
{ {
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock); sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {
@ -106,7 +106,7 @@ s32 sceKernelDeleteThread(s32 threadId)
{ {
sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId); sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {
@ -264,7 +264,7 @@ s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv:
{ {
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout); sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {

View File

@ -273,12 +273,11 @@ void SPUThread::do_dma_transfer(u32 cmd, spu_mfc_arg_t args)
const u32 index = (eal - SYS_SPU_THREAD_BASE_LOW) / SYS_SPU_THREAD_OFFSET; // thread number in group const u32 index = (eal - SYS_SPU_THREAD_BASE_LOW) / SYS_SPU_THREAD_OFFSET; // thread number in group
const u32 offset = (eal - SYS_SPU_THREAD_BASE_LOW) % SYS_SPU_THREAD_OFFSET; // LS offset or MMIO register const u32 offset = (eal - SYS_SPU_THREAD_BASE_LOW) % SYS_SPU_THREAD_OFFSET; // LS offset or MMIO register
std::shared_ptr<spu_group_t> group = tg.lock(); const auto group = tg.lock();
std::shared_ptr<CPUThread> t;
if (group && index < group->num && (t = group->threads[index])) if (group && index < group->num && group->threads[index])
{ {
auto& spu = static_cast<SPUThread&>(*t); auto& spu = static_cast<SPUThread&>(*group->threads[index]);
if (offset + args.size - 1 < 0x40000) // LS access if (offset + args.size - 1 < 0x40000) // LS access
{ {
@ -489,6 +488,7 @@ u32 SPUThread::get_ch_count(u32 ch)
switch (ch) switch (ch)
{ {
//case MFC_Cmd: return 16;
//case SPU_WrSRR0: return 1; break; //case SPU_WrSRR0: return 1; break;
//case SPU_RdSRR0: return 1; break; //case SPU_RdSRR0: return 1; break;
case SPU_WrOutMbox: return ch_out_mbox.get_count() ^ 1; break; case SPU_WrOutMbox: return ch_out_mbox.get_count() ^ 1; break;
@ -673,7 +673,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue = this->spup[spup].lock(); const auto queue = this->spup[spup].lock();
if (!queue) if (!queue)
{ {
@ -710,7 +710,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue = this->spup[spup].lock(); const auto queue = this->spup[spup].lock();
if (!queue) if (!queue)
{ {
@ -753,9 +753,9 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(data);
if (!Emu.GetIdManager().GetIDData(data, ef)) if (!ef)
{ {
return ch_in_mbox.push_uncond(CELL_ESRCH); return ch_in_mbox.push_uncond(CELL_ESRCH);
} }
@ -799,9 +799,9 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(data);
if (!Emu.GetIdManager().GetIDData(data, ef)) if (!ef)
{ {
return; return;
} }
@ -1121,7 +1121,7 @@ void SPUThread::stop_and_signal(u32 code)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group = tg.lock(); const auto group = tg.lock();
if (!group) if (!group)
{ {

View File

@ -2484,18 +2484,19 @@ void RSXThread::Task()
if (get_system_time() - start_time > m_vblank_count * 1000000 / 60) if (get_system_time() - start_time > m_vblank_count * 1000000 / 60)
{ {
m_vblank_count++; m_vblank_count++;
if (m_vblank_handler)
if (auto cb = m_vblank_handler)
{ {
auto cb = m_vblank_handler; Emu.GetCallbackManager().Async([=](PPUThread& CPU)
Emu.GetCallbackManager().Async([cb](PPUThread& CPU)
{ {
cb(CPU, 1); cb(CPU, 1);
}); });
} }
continue;
} }
else
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
} }
}); });

View File

@ -5,7 +5,7 @@
std::string SysCalls::GetFuncName(const u64 fid) std::string SysCalls::GetFuncName(const u64 fid)
{ {
// check syscalls // check syscalls
switch (fid) switch (~fid)
{ {
case 1: return "sys_process_getpid"; case 1: return "sys_process_getpid";
case 2: return "sys_process_wait_for_child"; case 2: return "sys_process_wait_for_child";
@ -26,7 +26,7 @@ std::string SysCalls::GetFuncName(const u64 fid)
case 29: return "sys_process_get_id"; case 29: return "sys_process_get_id";
case 30: return "_sys_process_get_paramsfo"; case 30: return "_sys_process_get_paramsfo";
case 31: return "sys_process_get_ppu_guid"; case 31: return "sys_process_get_ppu_guid";
case 41: return "sys_internal_ppu_thread_exit"; case 41: return "_sys_ppu_thread_exit";
case 43: return "sys_ppu_thread_yield"; case 43: return "sys_ppu_thread_yield";
case 44: return "sys_ppu_thread_join"; case 44: return "sys_ppu_thread_join";
case 45: return "sys_ppu_thread_detach"; case 45: return "sys_ppu_thread_detach";
@ -36,7 +36,7 @@ std::string SysCalls::GetFuncName(const u64 fid)
case 49: return "sys_ppu_thread_get_stack_information"; case 49: return "sys_ppu_thread_get_stack_information";
case 50: return "sys_ppu_thread_stop"; case 50: return "sys_ppu_thread_stop";
case 51: return "sys_ppu_thread_restart"; case 51: return "sys_ppu_thread_restart";
case 52: return "sys_ppu_thread_create"; case 52: return "_sys_ppu_thread_create";
case 53: return "sys_ppu_thread_start"; case 53: return "sys_ppu_thread_start";
case 56: return "sys_ppu_thread_rename"; case 56: return "sys_ppu_thread_rename";
case 57: return "sys_ppu_thread_recover_page_fault"; case 57: return "sys_ppu_thread_recover_page_fault";
@ -4414,5 +4414,5 @@ std::string SysCalls::GetFuncName(const u64 fid)
} }
} }
return fmt::format("0x%08llX", fid); return ~fid < 1024 ? fmt::format("syscall_%lld", ~fid) : fmt::format("0x%08llX", fid);
} }

View File

@ -206,25 +206,17 @@ s32 cellAudioInit()
auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality
{ {
if (port.level_inc) const auto param = port.level_set.read_sync();
{
port.level += port.level_inc;
if (port.level_inc > 0.0f) if (param.inc != 0.0f)
{
port.level += param.inc;
const bool dec = param.inc < 0.0f;
if ((!dec && param.value - port.level <= 0.0f) || (dec && param.value - port.level >= 0.0f))
{ {
if (port.level_set - port.level <= 0.0f) port.level = param.value;
{ port.level_set.compare_and_swap(param, { param.value, 0.0f });
port.level = port.level_set;
port.level_inc = 0.0f;
}
}
else
{
if (port.level_set - port.level >= 0.0f)
{
port.level = port.level_set;
port.level_inc = 0.0f;
}
} }
} }
}; };
@ -547,8 +539,7 @@ s32 cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
port.level = 1.0f; port.level = 1.0f;
} }
port.level_set = port.level; port.level_set.data = { port.level, 0.0f };
port.level_inc = 0.0f;
*portNum = port_index; *portNum = port_index;
cellAudio.Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index); cellAudio.Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index);
@ -754,10 +745,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
if (level >= 0.0f) if (level >= 0.0f)
{ {
std::lock_guard<std::mutex> lock(g_audio.mutex); port.level_set.exchange({ level, (port.level - level) / 624.0f });
port.level_set = level;
port.level_inc = (port.level - level) / 624.0f;
} }
else else
{ {

View File

@ -108,9 +108,15 @@ struct AudioPortConfig
u32 addr; u32 addr;
u32 read_index_addr; u32 read_index_addr;
u32 size; u32 size;
float level;
float level_set; struct level_set_t
float level_inc; {
float value;
float inc;
};
float level;
atomic_le_t<level_set_t> level_set;
}; };
struct AudioConfig //custom structure struct AudioConfig //custom structure

View File

@ -319,8 +319,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float); port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float);
port.tag = 0; port.tag = 0;
port.level = 1.0f; port.level = 1.0f;
port.level_set = 1.0f; port.level_set.data = { 1.0f, 0.0f };
port.level_inc = 0.0f;
libmixer.Warning("*** audio port opened (port=%d)", g_surmx.audio_port); libmixer.Warning("*** audio port opened (port=%d)", g_surmx.audio_port);

View File

@ -579,7 +579,7 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
lwmutex->recursive_count = 0; lwmutex->recursive_count = 0;
// call the syscall // call the syscall
s32 res = _sys_lwcond_queue_wait(lwcond->lwcond_queue, lwmutex->sleep_queue, timeout); s32 res = _sys_lwcond_queue_wait(CPU, lwcond->lwcond_queue, lwmutex->sleep_queue, timeout);
if (res == CELL_OK || res == CELL_ESRCH) if (res == CELL_OK || res == CELL_ESRCH)
{ {
@ -1210,6 +1210,65 @@ void sys_spinlock_unlock(vm::ptr<atomic_t<u32>> lock)
g_sys_spinlock_wm.notify(lock.addr()); g_sys_spinlock_wm.notify(lock.addr());
} }
s32 sys_ppu_thread_create(PPUThread& CPU, vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname)
{
sysPrxForUser.Warning("sys_ppu_thread_create(thread_id=*0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=*0x%x)", thread_id, entry, arg, prio, stacksize, flags, threadname);
// (allocate TLS)
// (return CELL_ENOMEM if failed)
// ...
vm::stackvar<ppu_thread_param_t> attr(CPU);
attr->entry = entry;
attr->tls = 0;
// call the syscall
if (s32 res = _sys_ppu_thread_create(thread_id, attr, arg, 0, prio, stacksize, flags, threadname))
{
return res;
}
// run the thread
return flags & SYS_PPU_THREAD_CREATE_INTERRUPT ? CELL_OK : sys_ppu_thread_start(static_cast<u32>(*thread_id));
}
s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr<u64> thread_id)
{
sysPrxForUser.Log("sys_ppu_thread_get_id(thread_id=*0x%x)", thread_id);
*thread_id = CPU.GetId();
return CELL_OK;
}
void sys_ppu_thread_exit(PPUThread& CPU, u64 val)
{
sysPrxForUser.Log("sys_ppu_thread_exit(val=0x%llx)", val);
// (call registered atexit functions)
// (deallocate TLS)
// ...
// call the syscall
_sys_ppu_thread_exit(CPU, val);
}
std::mutex g_once_mutex;
void sys_ppu_thread_once(PPUThread& CPU, vm::ptr<atomic_t<u32>> once_ctrl, vm::ptr<void()> init)
{
sysPrxForUser.Warning("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init);
std::lock_guard<std::mutex> lock(g_once_mutex);
if (once_ctrl->compare_and_swap_test(be_t<u32>::make(SYS_PPU_THREAD_ONCE_INIT), be_t<u32>::make(SYS_PPU_THREAD_DONE_INIT)))
{
// call init function using current thread context
init(CPU);
}
}
Module sysPrxForUser("sysPrxForUser", []() Module sysPrxForUser("sysPrxForUser", []()
{ {
g_tls_start = 0; g_tls_start = 0;

View File

@ -75,7 +75,7 @@ const ppu_func_caller sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, //32-40 UNS null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, //32-40 UNS
bind_func(sys_internal_ppu_thread_exit), //41 (0x029) bind_func(_sys_ppu_thread_exit), //41 (0x029)
null_func, //42 (0x02A) UNS null_func, //42 (0x02A) UNS
bind_func(sys_ppu_thread_yield), //43 (0x02B) bind_func(sys_ppu_thread_yield), //43 (0x02B)
bind_func(sys_ppu_thread_join), //44 (0x02C) bind_func(sys_ppu_thread_join), //44 (0x02C)
@ -86,8 +86,8 @@ const ppu_func_caller sc_table[1024] =
bind_func(sys_ppu_thread_get_stack_information), //49 (0x031) bind_func(sys_ppu_thread_get_stack_information), //49 (0x031)
null_func,//bind_func(sys_ppu_thread_stop), //50 (0x032) ROOT null_func,//bind_func(sys_ppu_thread_stop), //50 (0x032) ROOT
null_func,//bind_func(sys_ppu_thread_restart), //51 (0x033) ROOT null_func,//bind_func(sys_ppu_thread_restart), //51 (0x033) ROOT
null_func,//bind_func(sys_ppu_thread_create), //52 (0x034) DBG bind_func(_sys_ppu_thread_create), //52 (0x034) DBG
null_func,//bind_func(sys_ppu_thread_start), //53 (0x035) bind_func(sys_ppu_thread_start), //53 (0x035)
null_func,//bind_func(sys_ppu_...), //54 (0x036) ROOT null_func,//bind_func(sys_ppu_...), //54 (0x036) ROOT
null_func,//bind_func(sys_ppu_...), //55 (0x037) ROOT null_func,//bind_func(sys_ppu_...), //55 (0x037) ROOT
bind_func(sys_ppu_thread_rename), //56 (0x038) bind_func(sys_ppu_thread_rename), //56 (0x038)
@ -888,34 +888,32 @@ const ppu_func_caller sc_table[1024] =
void null_func(PPUThread& CPU) void null_func(PPUThread& CPU)
{ {
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", CPU.GPR[11], SysCalls::GetFuncName(CPU.GPR[11])); const auto code = CPU.GPR[11];
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", code, SysCalls::GetFuncName(~code));
CPU.GPR[3] = 0; CPU.GPR[3] = 0;
return;
} }
void SysCalls::DoSyscall(PPUThread& CPU, u64 code) void SysCalls::DoSyscall(PPUThread& CPU, u64 code)
{ {
auto old_last_syscall = CPU.m_last_syscall;
CPU.m_last_syscall = code;
if (code >= 1024) if (code >= 1024)
{ {
CPU.m_last_syscall = code;
throw "Invalid syscall number"; throw "Invalid syscall number";
} }
//Auto Pause using simple singleton. auto old_last_syscall = CPU.m_last_syscall;
Debug::AutoPause::getInstance().TryPause(code); CPU.m_last_syscall = ~code;
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(PPU, "Syscall %d called: %s", code, SysCalls::GetFuncName(code)); LOG_NOTICE(PPU, "Syscall %lld called: %s", code, SysCalls::GetFuncName(~code));
} }
sc_table[code](CPU); sc_table[code](CPU);
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(PPU, "Syscall %d finished: %s -> 0x%llx", code, SysCalls::GetFuncName(code), CPU.GPR[3]); LOG_NOTICE(PPU, "Syscall %lld finished: %s -> 0x%llx", code, SysCalls::GetFuncName(~code), CPU.GPR[3]);
} }
CPU.m_last_syscall = old_last_syscall; CPU.m_last_syscall = old_last_syscall;

View File

@ -149,7 +149,7 @@ u32 sleep_queue_t::signal(u32 protocol)
u64 sel = ~0ull; u64 sel = ~0ull;
for (auto& v : m_waiting) for (auto& v : m_waiting)
{ {
if (std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(v)) if (const auto t = Emu.GetCPU().GetThread(v))
{ {
const u64 prio = t->GetPrio(); const u64 prio = t->GetPrio();
if (prio < highest_prio) if (prio < highest_prio)

View File

@ -19,9 +19,9 @@ s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribu
LV2_LOCK; LV2_LOCK;
std::shared_ptr<mutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<mutex_t>(mutex_id);
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -50,14 +50,14 @@ s32 sys_cond_destroy(u32 cond_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<cond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<cond_t>(cond_id);
if (!Emu.GetIdManager().GetIDData(cond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (cond->waiters || cond->signaled) if (!cond->waiters.empty() || cond->signaled)
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
@ -78,17 +78,17 @@ s32 sys_cond_signal(u32 cond_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<cond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<cond_t>(cond_id);
if (!Emu.GetIdManager().GetIDData(cond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (cond->waiters) if (!cond->waiters.empty())
{ {
cond->signaled++; cond->signaled++;
cond->waiters--; cond->waiters.erase(cond->waiters.begin());
cond->cv.notify_one(); cond->cv.notify_one();
} }
@ -101,16 +101,17 @@ s32 sys_cond_signal_all(u32 cond_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<cond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<cond_t>(cond_id);
if (!Emu.GetIdManager().GetIDData(cond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (cond->waiters) if (const u32 count = cond->waiters.size())
{ {
cond->signaled += cond->waiters.exchange(0); cond->signaled += count;
cond->waiters.clear();
cond->cv.notify_all(); cond->cv.notify_all();
} }
@ -119,13 +120,13 @@ s32 sys_cond_signal_all(u32 cond_id)
s32 sys_cond_signal_to(u32 cond_id, u32 thread_id) s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
{ {
sys_cond.Todo("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id); sys_cond.Log("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id);
LV2_LOCK; LV2_LOCK;
std::shared_ptr<cond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<cond_t>(cond_id);
if (!Emu.GetIdManager().GetIDData(cond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -135,13 +136,15 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (!cond->waiters) const auto found = cond->waiters.find(thread_id);
if (found == cond->waiters.end())
{ {
return CELL_EPERM; return CELL_EPERM;
} }
cond->signaled++; cond->signaled++;
cond->waiters--; cond->waiters.erase(found);
cond->cv.notify_one(); cond->cv.notify_one();
return CELL_OK; return CELL_OK;
@ -155,22 +158,22 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<cond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<cond_t>(cond_id);
if (!Emu.GetIdManager().GetIDData(cond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> thread = Emu.GetCPU().GetThread(CPU.GetId()); const auto thread = Emu.GetCPU().GetThread(CPU.GetId());
if (cond->mutex->owner.owner_before(thread) || thread.owner_before(cond->mutex->owner)) // check equality if (cond->mutex->owner.owner_before(thread) || thread.owner_before(cond->mutex->owner)) // check equality
{ {
return CELL_EPERM; return CELL_EPERM;
} }
// protocol is ignored in current implementation // add waiter; protocol is ignored in current implementation
cond->waiters++; cond->waiters.emplace(CPU.GetId());
// unlock mutex // unlock mutex
cond->mutex->owner.reset(); cond->mutex->owner.reset();
@ -183,17 +186,21 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout)
// save recursive value // save recursive value
const u32 recursive_value = cond->mutex->recursive_count.exchange(0); const u32 recursive_value = cond->mutex->recursive_count.exchange(0);
while (!cond->mutex->owner.expired() || !cond->signaled) while (!cond->mutex->owner.expired() || !cond->signaled || cond->waiters.count(CPU.GetId()))
{ {
const bool is_timedout = timeout && get_system_time() - start_time > timeout; const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout only if no thread signaled (the flaw of avoiding sleep queue) // check timeout
if (is_timedout && cond->mutex->owner.expired() && !cond->signaled) if (is_timedout && cond->mutex->owner.expired())
{ {
// cancel waiting if the mutex is free, restore its owner and recursive value // cancel waiting if the mutex is free, restore its owner and recursive value
cond->mutex->owner = thread; cond->mutex->owner = thread;
cond->mutex->recursive_count = recursive_value; cond->mutex->recursive_count = recursive_value;
cond->waiters--;
if (!cond->waiters.erase(CPU.GetId()))
{
throw __FUNCTION__;
}
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }

View File

@ -24,9 +24,9 @@ struct cond_t
// TODO: use sleep queue, possibly remove condition variable // TODO: use sleep queue, possibly remove condition variable
std::condition_variable cv; std::condition_variable cv;
std::atomic<u32> waiters; std::unordered_set<u32> waiters;
cond_t(std::shared_ptr<mutex_t>& mutex, u64 name) cond_t(const std::shared_ptr<mutex_t>& mutex, u64 name)
: mutex(mutex) : mutex(mutex)
, name(name) , name(name)
, signaled(0) , signaled(0)

View File

@ -67,9 +67,9 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(equeue_id);
if (!Emu.GetIdManager().GetIDData(equeue_id, queue)) if (!queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -106,9 +106,9 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array,
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(equeue_id);
if (!Emu.GetIdManager().GetIDData(equeue_id, queue)) if (!queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -146,9 +146,9 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr<sys_event_t>
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(equeue_id);
if (!Emu.GetIdManager().GetIDData(equeue_id, queue)) if (!queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -203,14 +203,14 @@ s32 sys_event_queue_drain(u32 equeue_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(equeue_id);
if (!Emu.GetIdManager().GetIDData(equeue_id, queue)) if (!queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
queue->events = {}; queue->events.clear();
return CELL_OK; return CELL_OK;
} }
@ -245,9 +245,9 @@ s32 sys_event_port_destroy(u32 eport_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_port_t> port; const auto port = Emu.GetIdManager().GetIDData<event_port_t>(eport_id);
if (!Emu.GetIdManager().GetIDData(eport_id, port)) if (!port)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -268,10 +268,10 @@ s32 sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_port_t> port; const auto port = Emu.GetIdManager().GetIDData<event_port_t>(eport_id);
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(equeue_id);
if (!Emu.GetIdManager().GetIDData(eport_id, port) || !Emu.GetIdManager().GetIDData(equeue_id, queue)) if (!port || !queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -297,14 +297,14 @@ s32 sys_event_port_disconnect(u32 eport_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_port_t> port; const auto port = Emu.GetIdManager().GetIDData<event_port_t>(eport_id);
if (!Emu.GetIdManager().GetIDData(eport_id, port)) if (!port)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<event_queue_t> queue = port->queue.lock(); const auto queue = port->queue.lock();
if (!queue) if (!queue)
{ {
@ -313,16 +313,6 @@ s32 sys_event_port_disconnect(u32 eport_id)
// CELL_EBUSY is not returned // CELL_EBUSY is not returned
//const u64 source = port->name ? port->name : ((u64)process_getpid() << 32) | (u64)eport_id;
//for (auto& event : queue->events)
//{
// if (event.source == source)
// {
// return CELL_EBUSY; // ???
// }
//}
port->queue.reset(); port->queue.reset();
return CELL_OK; return CELL_OK;
@ -334,14 +324,14 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_port_t> port; const auto port = Emu.GetIdManager().GetIDData<event_port_t>(eport_id);
if (!Emu.GetIdManager().GetIDData(eport_id, port)) if (!port)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<event_queue_t> queue = port->queue.lock(); const auto queue = port->queue.lock();
if (!queue) if (!queue)
{ {

View File

@ -60,9 +60,9 @@ s32 sys_event_flag_destroy(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -105,9 +105,9 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 t
default: return CELL_EINVAL; default: return CELL_EINVAL;
} }
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -212,9 +212,9 @@ s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result)
default: return CELL_EINVAL; default: return CELL_EINVAL;
} }
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -252,9 +252,9 @@ s32 sys_event_flag_set(u32 id, u64 bitptn)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -280,9 +280,9 @@ s32 sys_event_flag_clear(u32 id, u64 bitptn)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -308,9 +308,9 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr<u32> num)
*num = 0; *num = 0;
} }
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -344,9 +344,9 @@ s32 sys_event_flag_get(u32 id, vm::ptr<u64> flags)
return CELL_EFAULT; return CELL_EFAULT;
} }
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(id);
if (!Emu.GetIdManager().GetIDData(id, ef)) if (!ef)
{ {
*flags = 0; *flags = 0;

View File

@ -135,9 +135,9 @@ s32 sys_fs_read(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread)
{ {
sys_fs.Log("sys_fs_read(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, nread); sys_fs.Log("sys_fs_read(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, nread);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file) || file->flags & CELL_FS_O_WRONLY) if (!file || file->flags & CELL_FS_O_WRONLY)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -153,9 +153,9 @@ s32 sys_fs_write(u32 fd, vm::ptr<const void> buf, u64 nbytes, vm::ptr<u64> nwrit
{ {
sys_fs.Log("sys_fs_write(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite); sys_fs.Log("sys_fs_write(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file) || !(file->flags & CELL_FS_O_ACCMODE)) if (!file || !(file->flags & CELL_FS_O_ACCMODE))
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -173,9 +173,9 @@ s32 sys_fs_close(u32 fd)
{ {
sys_fs.Log("sys_fs_close(fd=0x%x)", fd); sys_fs.Log("sys_fs_close(fd=0x%x)", fd);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -209,9 +209,9 @@ s32 sys_fs_readdir(u32 fd, vm::ptr<CellFsDirent> dir, vm::ptr<u64> nread)
{ {
sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread); sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread);
std::shared_ptr<vfsDirBase> directory; const auto directory = Emu.GetIdManager().GetIDData<vfsDirBase>(fd);
if (!Emu.GetIdManager().GetIDData(fd, directory)) if (!directory)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -237,9 +237,9 @@ s32 sys_fs_closedir(u32 fd)
{ {
sys_fs.Log("sys_fs_closedir(fd=0x%x)", fd); sys_fs.Log("sys_fs_closedir(fd=0x%x)", fd);
std::shared_ptr<vfsDirBase> directory; const auto directory = Emu.GetIdManager().GetIDData<vfsDirBase>(fd);
if (!Emu.GetIdManager().GetIDData(fd, directory)) if (!directory)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -336,9 +336,9 @@ s32 sys_fs_fstat(u32 fd, vm::ptr<CellFsStat> sb)
{ {
sys_fs.Warning("sys_fs_fstat(fd=0x%x, sb=*0x%x)", fd, sb); sys_fs.Warning("sys_fs_fstat(fd=0x%x, sb=*0x%x)", fd, sb);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -480,9 +480,9 @@ s32 sys_fs_lseek(u32 fd, s64 offset, s32 whence, vm::ptr<u64> pos)
return CELL_FS_EINVAL; return CELL_FS_EINVAL;
} }
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -498,11 +498,11 @@ s32 sys_fs_fget_block_size(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_
{ {
sys_fs.Todo("sys_fs_fget_block_size(fd=%d, sector_size=*0x%x, block_size=*0x%x, arg4=*0x%x, arg5=*0x%x)", fd, sector_size, block_size, arg4, arg5); sys_fs.Todo("sys_fs_fget_block_size(fd=%d, sector_size=*0x%x, block_size=*0x%x, arg4=*0x%x, arg5=*0x%x)", fd, sector_size, block_size, arg4, arg5);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
CELL_FS_EBADF; return CELL_FS_EBADF;
} }
*sector_size = 4096; // ? *sector_size = 4096; // ?
@ -558,13 +558,15 @@ s32 sys_fs_ftruncate(u32 fd, u64 size)
{ {
sys_fs.Warning("sys_fs_ftruncate(fd=0x%x, size=0x%llx)", fd, size); sys_fs.Warning("sys_fs_ftruncate(fd=0x%x, size=0x%llx)", fd, size);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
CELL_FS_EBADF; return CELL_FS_EBADF;
} }
std::lock_guard<std::mutex> lock(file->mutex);
u64 initialSize = file->file->GetSize(); u64 initialSize = file->file->GetSize();
if (initialSize < size) if (initialSize < size)

View File

@ -23,7 +23,7 @@ s32 sys_interrupt_tag_destroy(u32 intrtag)
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff); const auto t = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff);
if (!t) if (!t)
{ {
@ -58,7 +58,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u64 intrthread,
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff); const auto t = Emu.GetCPU().GetRawSPUThread(intrtag & 0xff);
if (!t) if (!t)
{ {
@ -71,7 +71,7 @@ s32 sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u64 intrthread,
// CELL_ESTAT is not returned (can't detect exact condition) // CELL_ESTAT is not returned (can't detect exact condition)
std::shared_ptr<CPUThread> it = Emu.GetCPU().GetThread((u32)intrthread); const auto it = Emu.GetCPU().GetThread((u32)intrthread);
if (!it) if (!it)
{ {
@ -132,8 +132,9 @@ s32 _sys_interrupt_thread_disestablish(u32 ih, vm::ptr<u64> r13)
{ {
sys_interrupt.Todo("_sys_interrupt_thread_disestablish(ih=0x%x, r13=*0x%x)", ih, r13); sys_interrupt.Todo("_sys_interrupt_thread_disestablish(ih=0x%x, r13=*0x%x)", ih, r13);
std::shared_ptr<interrupt_handler_t> handler; const auto handler = Emu.GetIdManager().GetIDData<interrupt_handler_t>(ih);
if (!Emu.GetIdManager().GetIDData(ih, handler))
if (!handler)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }

View File

@ -37,14 +37,14 @@ s32 _sys_lwcond_destroy(u32 lwcond_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwcond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<lwcond_t>(lwcond_id);
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) if (!cond)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (cond->waiters) if (!cond->waiters.empty() || cond->signaled1 || cond->signaled2)
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
@ -60,36 +60,26 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwcond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<lwcond_t>(lwcond_id);
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) if (!cond || (lwmutex_id && !mutex))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
{
return CELL_ESRCH;
}
// ppu_thread_id is ignored in current implementation
if (mode != 1 && mode != 2 && mode != 3) if (mode != 1 && mode != 2 && mode != 3)
{ {
sys_lwcond.Error("_sys_lwcond_signal(%d): invalid mode (%d)", lwcond_id, mode); sys_lwcond.Error("_sys_lwcond_signal(%d): invalid mode (%d)", lwcond_id, mode);
} }
if (~ppu_thread_id) const auto found = ~ppu_thread_id ? cond->waiters.find(ppu_thread_id) : cond->waiters.begin();
{
sys_lwcond.Todo("_sys_lwcond_signal(%d): ppu_thread_id (%d)", lwcond_id, ppu_thread_id);
}
if (mode == 1) if (mode == 1)
{ {
// mode 1: lightweight mutex was initially owned by the calling thread // mode 1: lightweight mutex was initially owned by the calling thread
if (!cond->waiters) if (found == cond->waiters.end())
{ {
return CELL_EPERM; return CELL_EPERM;
} }
@ -100,7 +90,7 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
{ {
// mode 2: lightweight mutex was not owned by the calling thread and waiter hasn't been increased // mode 2: lightweight mutex was not owned by the calling thread and waiter hasn't been increased
if (!cond->waiters) if (found == cond->waiters.end())
{ {
return CELL_OK; return CELL_OK;
} }
@ -111,7 +101,7 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
{ {
// in mode 3, lightweight mutex was forcefully owned by the calling thread // in mode 3, lightweight mutex was forcefully owned by the calling thread
if (!cond->waiters) if (found == cond->waiters.end())
{ {
return ~ppu_thread_id ? CELL_ENOENT : CELL_EPERM; return ~ppu_thread_id ? CELL_ENOENT : CELL_EPERM;
} }
@ -119,10 +109,8 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
cond->signaled1++; cond->signaled1++;
} }
if (--cond->waiters) cond->waiters.erase(found);
{ cond->cv.notify_one();
cond->cv.notify_one();
}
return CELL_OK; return CELL_OK;
} }
@ -133,15 +121,10 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwcond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<lwcond_t>(lwcond_id);
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) if (!cond || (lwmutex_id && !mutex))
{
return CELL_ESRCH;
}
if (lwmutex_id && !Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -151,10 +134,11 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
sys_lwcond.Error("_sys_lwcond_signal_all(%d): invalid mode (%d)", lwcond_id, mode); sys_lwcond.Error("_sys_lwcond_signal_all(%d): invalid mode (%d)", lwcond_id, mode);
} }
const s32 count = cond->waiters.exchange(0); const u32 count = cond->waiters.size();
if (count) if (count)
{ {
cond->waiters.clear();
cond->cv.notify_all(); cond->cv.notify_all();
} }
@ -176,7 +160,7 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
} }
} }
s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout) s32 _sys_lwcond_queue_wait(PPUThread& CPU, u32 lwcond_id, u32 lwmutex_id, u64 timeout)
{ {
sys_lwcond.Log("_sys_lwcond_queue_wait(lwcond_id=%d, lwmutex_id=%d, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout); sys_lwcond.Log("_sys_lwcond_queue_wait(lwcond_id=%d, lwmutex_id=%d, timeout=0x%llx)", lwcond_id, lwmutex_id, timeout);
@ -184,15 +168,10 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwcond_t> cond; const auto cond = Emu.GetIdManager().GetIDData<lwcond_t>(lwcond_id);
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwcond_id, cond)) if (!cond || !mutex)
{
return CELL_ESRCH;
}
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -205,18 +184,28 @@ s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout)
mutex->cv.notify_one(); mutex->cv.notify_one();
} }
// protocol is ignored in current implementation // add waiter; protocol is ignored in current implementation
cond->waiters++; cond->waiters.emplace(CPU.GetId());
while (!(cond->signaled1 && mutex->signaled) && !cond->signaled2) while ((!(cond->signaled1 && mutex->signaled) && !cond->signaled2) || cond->waiters.count(CPU.GetId()))
{ {
const bool is_timedout = timeout && get_system_time() - start_time > timeout; const bool is_timedout = timeout && get_system_time() - start_time > timeout;
// check timeout only if no thread signaled in mode 1 (the flaw of avoiding sleep queue) // check timeout
if (is_timedout && !cond->signaled1) if (is_timedout)
{ {
// cancel waiting // cancel waiting
cond->waiters--; if (!cond->waiters.erase(CPU.GetId()))
{
if (cond->signaled1 && !mutex->signaled)
{
cond->signaled1--;
}
else
{
throw __FUNCTION__;
}
}
if (mutex->signaled) if (mutex->signaled)
{ {

View File

@ -26,7 +26,7 @@ struct lwcond_t
// TODO: use sleep queue // TODO: use sleep queue
std::condition_variable cv; std::condition_variable cv;
std::atomic<u32> waiters; std::unordered_set<u32> waiters;
lwcond_t(u64 name) lwcond_t(u64 name)
: name(name) : name(name)
@ -47,4 +47,4 @@ s32 _sys_lwcond_create(vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sys_lwcon
s32 _sys_lwcond_destroy(u32 lwcond_id); s32 _sys_lwcond_destroy(u32 lwcond_id);
s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mode); s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mode);
s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode); s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode);
s32 _sys_lwcond_queue_wait(u32 lwcond_id, u32 lwmutex_id, u64 timeout); s32 _sys_lwcond_queue_wait(PPUThread& CPU, u32 lwcond_id, u32 lwmutex_id, u64 timeout);

View File

@ -52,9 +52,9 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -77,9 +77,9 @@ s32 _sys_lwmutex_lock(u32 lwmutex_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -117,9 +117,9 @@ s32 _sys_lwmutex_trylock(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -140,9 +140,9 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<lwmutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<lwmutex_t>(lwmutex_id);
if (!Emu.GetIdManager().GetIDData(lwmutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }

View File

@ -54,9 +54,9 @@ s32 sys_mutex_destroy(u32 mutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<mutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<mutex_t>(mutex_id);
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -90,14 +90,14 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<mutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<mutex_t>(mutex_id);
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> thread = Emu.GetCPU().GetThread(CPU.GetId(), CPU_THREAD_PPU); const auto thread = Emu.GetCPU().GetThread(CPU.GetId(), CPU_THREAD_PPU);
if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality
{ {
@ -148,14 +148,14 @@ s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<mutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<mutex_t>(mutex_id);
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> thread = Emu.GetCPU().GetThread(CPU.GetId()); const auto thread = Emu.GetCPU().GetThread(CPU.GetId());
if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality
{ {
@ -190,16 +190,16 @@ s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<mutex_t> mutex; const auto mutex = Emu.GetIdManager().GetIDData<mutex_t>(mutex_id);
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) if (!mutex)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
std::shared_ptr<CPUThread> thread = Emu.GetCPU().GetThread(CPU.GetId()); const auto thread = Emu.GetCPU().GetThread(CPU.GetId());
if (mutex->owner.owner_before(thread) || thread.owner_before(mutex->owner)) // check equality if (mutex->owner.owner_before(thread) || thread.owner_before(mutex->owner)) // check inequality
{ {
return CELL_EPERM; return CELL_EPERM;
} }

View File

@ -10,8 +10,10 @@
SysCallBase sys_ppu_thread("sys_ppu_thread"); SysCallBase sys_ppu_thread("sys_ppu_thread");
void ppu_thread_exit(PPUThread& CPU, u64 errorcode) void _sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode)
{ {
sys_ppu_thread.Warning("_sys_ppu_thread_exit(errorcode=0x%llx)", errorcode);
CPU.SetExitStatus(errorcode); CPU.SetExitStatus(errorcode);
CPU.Stop(); CPU.Stop();
@ -25,37 +27,25 @@ void ppu_thread_exit(PPUThread& CPU, u64 errorcode)
} }
} }
void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode) void sys_ppu_thread_yield()
{
sys_ppu_thread.Log("sys_ppu_thread_exit(0x%llx)", errorcode);
ppu_thread_exit(CPU, errorcode);
}
void sys_internal_ppu_thread_exit(PPUThread& CPU, u64 errorcode)
{
sys_ppu_thread.Warning("sys_internal_ppu_thread_exit(0x%llx)", errorcode);
ppu_thread_exit(CPU, errorcode);
}
s32 sys_ppu_thread_yield()
{ {
sys_ppu_thread.Log("sys_ppu_thread_yield()"); sys_ppu_thread.Log("sys_ppu_thread_yield()");
// Note: Or do we actually want to yield? // Note: Or do we actually want to yield?
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
return CELL_OK;
} }
s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<u64> vptr) s32 sys_ppu_thread_join(u32 thread_id, vm::ptr<u64> vptr)
{ {
sys_ppu_thread.Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.addr()); sys_ppu_thread.Warning("sys_ppu_thread_join(thread_id=%d, vptr=*0x%x)", thread_id, vptr);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id); const auto t = Emu.GetCPU().GetThread(thread_id);
if (!thr) return
CELL_ESRCH;
while (thr->IsAlive()) if (!t)
{
return CELL_ESRCH;
}
while (t->IsAlive())
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -65,98 +55,117 @@ s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<u64> vptr)
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }
*vptr = thr->GetExitStatus(); *vptr = t->GetExitStatus();
Emu.GetCPU().RemoveThread(thread_id); Emu.GetCPU().RemoveThread(thread_id);
return CELL_OK; return CELL_OK;
} }
s32 sys_ppu_thread_detach(u64 thread_id) s32 sys_ppu_thread_detach(u32 thread_id)
{ {
sys_ppu_thread.Todo("sys_ppu_thread_detach(thread_id=%lld)", thread_id); sys_ppu_thread.Warning("sys_ppu_thread_detach(thread_id=%d)", thread_id);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id); const auto t = Emu.GetCPU().GetThread(thread_id);
if (!thr)
if (!t)
{
return CELL_ESRCH; return CELL_ESRCH;
}
if (!thr->IsJoinable()) if (!t->IsJoinable())
{
return CELL_EINVAL; return CELL_EINVAL;
thr->SetJoinable(false); }
t->SetJoinable(false);
return CELL_OK; return CELL_OK;
} }
void sys_ppu_thread_get_join_state(PPUThread& CPU, vm::ptr<s32> isjoinable) void sys_ppu_thread_get_join_state(PPUThread& CPU, vm::ptr<s32> isjoinable)
{ {
sys_ppu_thread.Warning("sys_ppu_thread_get_join_state(isjoinable_addr=0x%x)", isjoinable.addr()); sys_ppu_thread.Warning("sys_ppu_thread_get_join_state(isjoinable=*0x%x)", isjoinable);
*isjoinable = CPU.IsJoinable(); *isjoinable = CPU.IsJoinable();
} }
s32 sys_ppu_thread_set_priority(u64 thread_id, s32 prio) s32 sys_ppu_thread_set_priority(u32 thread_id, s32 prio)
{ {
sys_ppu_thread.Log("sys_ppu_thread_set_priority(thread_id=%lld, prio=%d)", thread_id, prio); sys_ppu_thread.Log("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id); const auto t = Emu.GetCPU().GetThread(thread_id);
if (!thr)
if (!t)
{
return CELL_ESRCH; return CELL_ESRCH;
}
thr->SetPrio(prio); t->SetPrio(prio);
return CELL_OK; return CELL_OK;
} }
s32 sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr) s32 sys_ppu_thread_get_priority(u32 thread_id, vm::ptr<s32> priop)
{ {
sys_ppu_thread.Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr); sys_ppu_thread.Log("sys_ppu_thread_get_priority(thread_id=%d, priop=*0x%x)", thread_id, priop);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id); const auto t = Emu.GetCPU().GetThread(thread_id);
if(!thr) return CELL_ESRCH;
vm::write32(prio_addr, (s32)thr->GetPrio()); if (!t)
{
return CELL_OK;
}
s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr)
{
sys_ppu_thread.Log("sys_ppu_thread_get_stack_information(info_addr=0x%x)", info_addr);
vm::write32(info_addr, (u32)CPU.GetStackAddr());
vm::write32(info_addr + 4, CPU.GetStackSize());
return CELL_OK;
}
s32 sys_ppu_thread_stop(u64 thread_id)
{
sys_ppu_thread.Warning("sys_ppu_thread_stop(thread_id=%lld)", thread_id);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id);
if (!thr)
return CELL_ESRCH; return CELL_ESRCH;
}
thr->Stop(); *priop = static_cast<s32>(t->GetPrio());
return CELL_OK; return CELL_OK;
} }
s32 sys_ppu_thread_restart(u64 thread_id) s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, vm::ptr<sys_ppu_thread_stack_t> sp)
{ {
sys_ppu_thread.Warning("sys_ppu_thread_restart(thread_id=%lld)", thread_id); sys_ppu_thread.Log("sys_ppu_thread_get_stack_information(sp=*0x%x)", sp);
std::shared_ptr<CPUThread> thr = Emu.GetCPU().GetThread(thread_id); sp->pst_addr = CPU.GetStackAddr();
if (!thr) sp->pst_size = CPU.GetStackSize();
return CELL_OK;
}
s32 sys_ppu_thread_stop(u32 thread_id)
{
sys_ppu_thread.Error("sys_ppu_thread_stop(thread_id=%d)", thread_id);
const auto t = Emu.GetCPU().GetThread(thread_id);
if (!t)
{
return CELL_ESRCH; return CELL_ESRCH;
}
thr->Stop(); t->Stop();
thr->Run();
return CELL_OK;
}
s32 sys_ppu_thread_restart(u32 thread_id)
{
sys_ppu_thread.Error("sys_ppu_thread_restart(thread_id=%d)", thread_id);
const auto t = Emu.GetCPU().GetThread(thread_id);
if (!t)
{
return CELL_ESRCH;
}
t->Stop();
t->Run();
return CELL_OK; return CELL_OK;
} }
u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, std::string name, std::function<void(PPUThread&)> task) u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, std::string name, std::function<void(PPUThread&)> task)
{ {
auto new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); const auto new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
auto& ppu = static_cast<PPUThread&>(*new_thread); auto& ppu = static_cast<PPUThread&>(*new_thread);
@ -177,54 +186,69 @@ u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joina
return ppu.GetId(); return ppu.GetId();
} }
s32 sys_ppu_thread_create(vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname) s32 _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 unk, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname)
{ {
sys_ppu_thread.Warning("sys_ppu_thread_create(thread_id=*0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=*0x%x)", thread_id, entry, arg, prio, stacksize, flags, threadname); sys_ppu_thread.Warning("_sys_ppu_thread_create(thread_id=*0x%x, param=*0x%x, arg=0x%llx, unk=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=*0x%x)",
thread_id, param, arg, unk, prio, stacksize, flags, threadname);
if (prio < 0 || prio > 3071) if (prio < 0 || prio > 3071)
{ {
return CELL_EINVAL; return CELL_EINVAL;
} }
bool is_joinable = flags & SYS_PPU_THREAD_CREATE_JOINABLE; const bool is_joinable = flags & SYS_PPU_THREAD_CREATE_JOINABLE;
bool is_interrupt = flags & SYS_PPU_THREAD_CREATE_INTERRUPT; const bool is_interrupt = flags & SYS_PPU_THREAD_CREATE_INTERRUPT;
if (is_joinable && is_interrupt) if (is_joinable && is_interrupt)
{ {
return CELL_EPERM; return CELL_EPERM;
} }
*thread_id = ppu_thread_create(entry, arg, prio, stacksize, is_joinable, is_interrupt, threadname ? threadname.get_ptr() : ""); const auto new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
return CELL_OK;
}
std::mutex g_once_mutex; auto& ppu = static_cast<PPUThread&>(*new_thread);
void sys_ppu_thread_once(PPUThread& CPU, vm::ptr<atomic_t<u32>> once_ctrl, vm::ptr<void()> init) ppu.SetEntry(param->entry);
{ ppu.SetPrio(prio);
sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init); ppu.SetStackSize(stacksize < 0x4000 ? 0x4000 : stacksize); // (hack) adjust minimal stack size
ppu.SetJoinable(is_joinable);
ppu.SetName(threadname.get_ptr());
ppu.Run();
std::lock_guard<std::mutex> lock(g_once_mutex); ppu.GPR[3] = arg;
ppu.GPR[4] = unk; // actually unknown
if (once_ctrl->compare_and_swap_test(be_t<u32>::make(SYS_PPU_THREAD_ONCE_INIT), be_t<u32>::make(SYS_PPU_THREAD_DONE_INIT))) if (u32 tls = param->tls) // hack
{ {
init(CPU); ppu.GPR[13] = tls;
} }
}
s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr<u64> thread_id) *thread_id = ppu.GetId();
{
sys_ppu_thread.Log("sys_ppu_thread_get_id(thread_id_addr=0x%x)", thread_id.addr());
*thread_id = CPU.GetId();
return CELL_OK; return CELL_OK;
} }
s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr<const char> name) s32 sys_ppu_thread_start(u32 thread_id)
{ {
sys_ppu_thread.Log("sys_ppu_thread_rename(thread_id=0x%llx, name=*0x%x)", thread_id, name); sys_ppu_thread.Warning("sys_ppu_thread_start(thread_id=%d)", thread_id);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(thread_id, CPU_THREAD_PPU); const auto t = Emu.GetCPU().GetThread(thread_id, CPU_THREAD_PPU);
if (!t)
{
return CELL_ESRCH;
}
t->Exec();
return CELL_OK;
}
s32 sys_ppu_thread_rename(u32 thread_id, vm::ptr<const char> name)
{
sys_ppu_thread.Error("sys_ppu_thread_rename(thread_id=%d, name=*0x%x)", thread_id, name);
const auto t = Emu.GetCPU().GetThread(thread_id, CPU_THREAD_PPU);
if (!t) if (!t)
{ {
@ -232,5 +256,6 @@ s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr<const char> name)
} }
t->SetThreadName(name.get_ptr()); t->SetThreadName(name.get_ptr());
return CELL_OK; return CELL_OK;
} }

View File

@ -15,22 +15,32 @@ enum : u64
SYS_PPU_THREAD_CREATE_INTERRUPT = 0x2, SYS_PPU_THREAD_CREATE_INTERRUPT = 0x2,
}; };
struct sys_ppu_thread_stack_t
{
u32 pst_addr;
u32 pst_size;
};
struct ppu_thread_param_t
{
u32 entry;
u32 tls;
};
// Aux // Aux
u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, std::string name, std::function<void(PPUThread&)> task = nullptr); u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool is_joinable, bool is_interrupt, std::string name, std::function<void(PPUThread&)> task = nullptr);
// SysCalls // SysCalls
void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode); void _sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode);
void sys_internal_ppu_thread_exit(PPUThread& CPU, u64 errorcode); void sys_ppu_thread_yield();
s32 sys_ppu_thread_yield(); s32 sys_ppu_thread_join(u32 thread_id, vm::ptr<u64> vptr);
s32 sys_ppu_thread_join(u64 thread_id, vm::ptr<u64> vptr); s32 sys_ppu_thread_detach(u32 thread_id);
s32 sys_ppu_thread_detach(u64 thread_id);
void sys_ppu_thread_get_join_state(PPUThread& CPU, vm::ptr<s32> isjoinable); void sys_ppu_thread_get_join_state(PPUThread& CPU, vm::ptr<s32> isjoinable);
s32 sys_ppu_thread_set_priority(u64 thread_id, s32 prio); s32 sys_ppu_thread_set_priority(u32 thread_id, s32 prio);
s32 sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr); s32 sys_ppu_thread_get_priority(u32 thread_id, vm::ptr<s32> priop);
s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr); s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, vm::ptr<sys_ppu_thread_stack_t> sp);
s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_stop(u32 thread_id);
s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_restart(u32 thread_id);
s32 sys_ppu_thread_create(vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname); s32 _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 arg4, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname);
void sys_ppu_thread_once(PPUThread& CPU, vm::ptr<atomic_t<u32>> once_ctrl, vm::ptr<void()> init); s32 sys_ppu_thread_start(u32 thread_id);
s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr<u64> thread_id); s32 sys_ppu_thread_rename(u32 thread_id, vm::ptr<const char> name);
s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr<const char> name);

View File

@ -99,7 +99,7 @@ u32 spu_thread_initialize(u32 group_id, u32 spu_num, vm::ptr<sys_spu_image> img,
sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option); sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option);
} }
auto t = Emu.GetCPU().AddThread(CPU_THREAD_SPU); const auto t = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
auto& spu = static_cast<SPUThread&>(*t); auto& spu = static_cast<SPUThread&>(*t);
@ -108,8 +108,7 @@ u32 spu_thread_initialize(u32 group_id, u32 spu_num, vm::ptr<sys_spu_image> img,
spu.SetName(name); spu.SetName(name);
spu.m_custom_task = task; spu.m_custom_task = task;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(group_id);
Emu.GetIdManager().GetIDData(group_id, group);
spu.tg = group; spu.tg = group;
group->threads[spu_num] = t; group->threads[spu_num] = t;
@ -141,8 +140,9 @@ s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group_id, u32 spu_num, vm
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(group_id);
if (!Emu.GetIdManager().GetIDData(group_id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -167,7 +167,8 @@ s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
return CELL_ESRCH; return CELL_ESRCH;
@ -175,7 +176,7 @@ s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg)
auto& spu = static_cast<SPUThread&>(*t); auto& spu = static_cast<SPUThread&>(*t);
std::shared_ptr<spu_group_t> group = spu.tg.lock(); const auto group = spu.tg.lock();
assert(spu.index < group->threads.size()); assert(spu.index < group->threads.size());
@ -193,7 +194,7 @@ s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<u32> status)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -246,8 +247,9 @@ s32 sys_spu_thread_group_destroy(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -283,8 +285,9 @@ s32 sys_spu_thread_group_start(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -326,7 +329,7 @@ s32 sys_spu_thread_group_start(u32 id)
// because SPU_THREAD_GROUP_STATUS_READY is not possible, run event is delivered immediately // because SPU_THREAD_GROUP_STATUS_READY is not possible, run event is delivered immediately
if (std::shared_ptr<event_queue_t> queue = group->ep_run.lock()) if (auto queue = group->ep_run.lock())
{ {
queue->push(SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY, id, 0, 0); // TODO: check data2 and data3 queue->push(SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY, id, 0, 0); // TODO: check data2 and data3
} }
@ -348,8 +351,9 @@ s32 sys_spu_thread_group_suspend(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -402,8 +406,9 @@ s32 sys_spu_thread_group_resume(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -448,15 +453,16 @@ s32 sys_spu_thread_group_yield(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
if (group->state != SPU_THREAD_GROUP_STATUS_RUNNING) if (group->state != SPU_THREAD_GROUP_STATUS_RUNNING)
{ {
return CELL_EINVAL; return CELL_ESTAT;
} }
// SPU_THREAD_GROUP_STATUS_READY state is not used, so this function does nothing // SPU_THREAD_GROUP_STATUS_READY state is not used, so this function does nothing
@ -471,11 +477,10 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value)
LV2_LOCK; LV2_LOCK;
// seems the id can be either SPU Thread Group or SPU Thread // seems the id can be either SPU Thread Group or SPU Thread
auto thread = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
std::shared_ptr<spu_group_t> group; if (!group && !thread)
std::shared_ptr<CPUThread> thread = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!Emu.GetIdManager().GetIDData(id, group) && !thread)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -510,7 +515,7 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value)
if (group->state <= SPU_THREAD_GROUP_STATUS_INITIALIZED || group->state == SPU_THREAD_GROUP_STATUS_WAITING || group->state == SPU_THREAD_GROUP_STATUS_WAITING) if (group->state <= SPU_THREAD_GROUP_STATUS_INITIALIZED || group->state == SPU_THREAD_GROUP_STATUS_WAITING || group->state == SPU_THREAD_GROUP_STATUS_WAITING)
{ {
return CELL_EINVAL; return CELL_ESTAT;
} }
for (auto& t : group->threads) for (auto& t : group->threads)
@ -538,8 +543,9 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -621,7 +627,7 @@ s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
{ {
sys_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=%d)", id, address, value, type); sys_spu.Log("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=%d)", id, address, value, type);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -656,7 +662,7 @@ s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<u64> value, u32 type)
{ {
sys_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value=*0x%x, type=%d)", id, address, value, type); sys_spu.Log("sys_spu_thread_read_ls(id=%d, address=0x%x, value=*0x%x, type=%d)", id, address, value, type);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -691,7 +697,7 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
{ {
sys_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); sys_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -709,7 +715,7 @@ s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value)
{ {
sys_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value); sys_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -732,7 +738,7 @@ s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<u64> value)
{ {
sys_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value=*0x%x)", id, value); sys_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value=*0x%x)", id, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -750,7 +756,7 @@ s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
{ {
sys_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value); sys_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -775,10 +781,10 @@ s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(eq);
if (!Emu.GetIdManager().GetIDData(id, group) || !Emu.GetIdManager().GetIDData(eq, queue)) if (!group || !queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -831,9 +837,9 @@ s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group)) if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -894,11 +900,10 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(eq);
std::shared_ptr<event_queue_t> queue; if (!t || !queue)
if (!t || !Emu.GetIdManager().GetIDData(eq, queue))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -929,7 +934,7 @@ s32 sys_spu_thread_disconnect_event(u32 id, u32 et, u8 spup)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -962,11 +967,10 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(spuq);
std::shared_ptr<event_queue_t> queue; if (!t || !queue)
if (!t || !Emu.GetIdManager().GetIDData(spuq, queue))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -1009,7 +1013,7 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU); const auto t = Emu.GetCPU().GetThread(id, CPU_THREAD_SPU);
if (!t) if (!t)
{ {
@ -1037,10 +1041,10 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, vm::
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
std::shared_ptr<event_queue_t> queue; const auto queue = Emu.GetIdManager().GetIDData<event_queue_t>(eq);
if (!Emu.GetIdManager().GetIDData(id, group) || !Emu.GetIdManager().GetIDData(eq, queue)) if (!group || !queue)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -1112,8 +1116,9 @@ s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group; const auto group = Emu.GetIdManager().GetIDData<spu_group_t>(id);
if (!Emu.GetIdManager().GetIDData(id, group))
if (!group)
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
@ -1142,7 +1147,7 @@ s32 sys_raw_spu_create(vm::ptr<u32> id, vm::ptr<void> attr)
LV2_LOCK; LV2_LOCK;
auto t = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU); const auto t = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
if (!t) if (!t)
{ {
@ -1164,7 +1169,7 @@ s32 sys_raw_spu_destroy(u32 id)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1191,7 +1196,7 @@ s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr
return CELL_EINVAL; return CELL_EINVAL;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1221,7 +1226,7 @@ s32 sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask)
return CELL_EINVAL; return CELL_EINVAL;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1244,7 +1249,7 @@ s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ptr<u64> mask)
return CELL_EINVAL; return CELL_EINVAL;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1267,7 +1272,7 @@ s32 sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat)
return CELL_EINVAL; return CELL_EINVAL;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1290,7 +1295,7 @@ s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr<u64> stat)
return CELL_EINVAL; return CELL_EINVAL;
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1308,7 +1313,7 @@ s32 sys_raw_spu_read_puint_mb(u32 id, vm::ptr<u32> value)
{ {
sys_spu.Log("sys_raw_spu_read_puint_mb(id=%d, value=*0x%x)", id, value); sys_spu.Log("sys_raw_spu_read_puint_mb(id=%d, value=*0x%x)", id, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1331,7 +1336,7 @@ s32 sys_raw_spu_set_spu_cfg(u32 id, u32 value)
sys_spu.Fatal("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value); sys_spu.Fatal("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value);
} }
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {
@ -1349,7 +1354,7 @@ s32 sys_raw_spu_get_spu_cfg(u32 id, vm::ptr<u32> value)
{ {
sys_spu.Log("sys_raw_spu_get_spu_afg(id=%d, value=*0x%x)", id, value); sys_spu.Log("sys_raw_spu_get_spu_afg(id=%d, value=*0x%x)", id, value);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetRawSPUThread(id); const auto t = Emu.GetCPU().GetRawSPUThread(id);
if (!t) if (!t)
{ {