sys_semaphore improved

This commit is contained in:
Nekotekina 2015-07-21 14:55:29 +03:00
parent 0aefaec46e
commit 023d385af8
6 changed files with 255 additions and 235 deletions

View file

@ -42,27 +42,27 @@ bool spursIsLibProfLoaded();
//
// SPURS core functions
//
s32 spursCreateLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<u32> queueId, vm::ptr<u8> port, s32 size, vm::cptr<char> name);
s32 spursAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool spursCreated);
s32 spursCreateLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32> queueId, vm::ptr<u8> port, s32 size, vm::cptr<char> name);
s32 spursAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool spursCreated);
s32 spursDetachLv2EventQueue(vm::ptr<CellSpurs> spurs, u8 spuPort, bool spursCreated);
void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
void spursHandlerEntry(PPUThread& CPU);
void spursHandlerWaitReady(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
void spursHandlerEntry(PPUThread& ppu);
s32 spursCreateHandler(vm::ptr<CellSpurs> spurs, u32 ppuPriority);
s32 spursInvokeEventHandlers(PPUThread& CPU, vm::ptr<CellSpurs::EventPortMux> eventPortMux);
s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 wid);
void spursEventHelperEntry(PPUThread& CPU);
s32 spursCreateSpursEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 ppuPriority);
s32 spursInvokeEventHandlers(PPUThread& ppu, vm::ptr<CellSpurs::EventPortMux> eventPortMux);
s32 spursWakeUpShutdownCompletionWaiter(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 wid);
void spursEventHelperEntry(PPUThread& ppu);
s32 spursCreateSpursEventHelper(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 ppuPriority);
void spursInitialiseEventPortMux(vm::ptr<CellSpurs::EventPortMux> eventPortMux, u8 spuPort, u32 eventPort, u32 unknown);
s32 spursAddDefaultSystemWorkload(vm::ptr<CellSpurs> spurs, vm::cptr<u8> swlPriority, u32 swlMaxSpu, u32 swlIsPreem);
s32 spursFinalizeSpu(vm::ptr<CellSpurs> spurs);
s32 spursStopEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
s32 spursSignalToHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
s32 spursJoinHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
s32 spursInit(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 revision, u32 sdkVersion, s32 nSpus, s32 spuPriority, s32 ppuPriority, u32 flags,
s32 spursStopEventHelper(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursSignalToHandlerThread(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursJoinHandlerThread(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursInit(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 revision, u32 sdkVersion, s32 nSpus, s32 spuPriority, s32 ppuPriority, u32 flags,
vm::cptr<char> prefix, u32 prefixSize, u32 container, vm::cptr<u8> swlPriority, u32 swlMaxSpu, u32 swlIsPreem);
s32 cellSpursInitialize(PPUThread& CPU, vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork);
s32 cellSpursInitializeWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr);
s32 cellSpursInitializeWithAttribute2(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr);
s32 cellSpursInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork);
s32 cellSpursInitializeWithAttribute(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr);
s32 cellSpursInitializeWithAttribute2(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr);
s32 _cellSpursAttributeInitialize(vm::ptr<CellSpursAttribute> attr, u32 revision, u32 sdkVersion, u32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork);
s32 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr<CellSpursAttribute> attr, u32 container);
s32 cellSpursAttributeSetNamePrefix(vm::ptr<CellSpursAttribute> attr, vm::cptr<char> prefix, u32 size);
@ -76,7 +76,7 @@ s32 cellSpursGetSpuThreadId(vm::ptr<CellSpurs> spurs, vm::ptr<u32> thread, vm::p
s32 cellSpursSetMaxContention(vm::ptr<CellSpurs> spurs, u32 wid, u32 maxContention);
s32 cellSpursSetPriorities(vm::ptr<CellSpurs> spurs, u32 wid, vm::cptr<u8> priorities);
s32 cellSpursSetPreemptionVictimHints(vm::ptr<CellSpurs> spurs, vm::cptr<bool> isPreemptible);
s32 cellSpursAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic);
s32 cellSpursAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic);
s32 cellSpursDetachLv2EventQueue(vm::ptr<CellSpurs> spurs, u8 port);
s32 cellSpursEnableExceptionEventHandler(vm::ptr<CellSpurs> spurs, bool flag);
s32 cellSpursSetGlobalExceptionEventHandler(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursGlobalExceptionEventHandler> eaHandler, vm::ptr<void> arg);
@ -91,14 +91,14 @@ s32 cellSpursGetSpuGuid();
//
// SPURS trace functions
//
void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs);
s32 spursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode, u32 updateStatus);
s32 cellSpursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode);
s32 cellSpursTraceFinalize(vm::ptr<CellSpurs> spurs);
s32 spursTraceStart(vm::ptr<CellSpurs> spurs, u32 updateStatus);
s32 cellSpursTraceStart(vm::ptr<CellSpurs> spurs);
s32 spursTraceStop(vm::ptr<CellSpurs> spurs, u32 updateStatus);
s32 cellSpursTraceStop(vm::ptr<CellSpurs> spurs);
void spursTraceStatusUpdate(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursTraceInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode, u32 updateStatus);
s32 cellSpursTraceInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode);
s32 cellSpursTraceFinalize(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursTraceStart(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 updateStatus);
s32 cellSpursTraceStart(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 spursTraceStop(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 updateStatus);
s32 cellSpursTraceStop(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
//
// SPURS policy module functions
@ -113,7 +113,7 @@ s32 cellSpursAddWorkloadWithAttribute(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid
s32 cellSpursShutdownWorkload();
s32 cellSpursWaitForWorkloadShutdown();
s32 cellSpursRemoveWorkload();
s32 cellSpursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs);
s32 cellSpursWakeUp(PPUThread& ppu, vm::ptr<CellSpurs> spurs);
s32 cellSpursSendWorkloadSignal(vm::ptr<CellSpurs> spurs, u32 wid);
s32 cellSpursGetWorkloadFlag(vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursWorkloadFlag> flag);
s32 cellSpursReadyCountStore(vm::ptr<CellSpurs> spurs, u32 wid, u32 value);
@ -131,9 +131,9 @@ s32 cellSpursRequestIdleSpu();
//
// SPURS taskset functions
//
s32 spursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 max_contention, vm::cptr<char> name, u32 size, s32 enable_clear_ls);
s32 cellSpursCreateTasksetWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute> attr);
s32 cellSpursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 maxContention);
s32 spursCreateTaskset(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 max_contention, vm::cptr<char> name, u32 size, s32 enable_clear_ls);
s32 cellSpursCreateTasksetWithAttribute(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute> attr);
s32 cellSpursCreateTaskset(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 maxContention);
s32 cellSpursJoinTaskset(vm::ptr<CellSpursTaskset> taskset);
s32 cellSpursGetTasksetId(vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> wid);
s32 cellSpursShutdownTaskset(vm::ptr<CellSpursTaskset> taskset);
@ -141,11 +141,11 @@ s32 cellSpursTasksetAttributeSetName(vm::ptr<CellSpursTasksetAttribute> attr, vm
s32 cellSpursTasksetAttributeSetTasksetSize(vm::ptr<CellSpursTasksetAttribute> attr, u32 size);
s32 cellSpursTasksetAttributeEnableClearLS(vm::ptr<CellSpursTasksetAttribute> attr, s32 enable);
s32 _cellSpursTasksetAttribute2Initialize(vm::ptr<CellSpursTasksetAttribute2> attribute, u32 revision);
s32 cellSpursCreateTaskset2(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute2> attr);
s32 cellSpursCreateTaskset2(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute2> attr);
s32 cellSpursDestroyTaskset2();
s32 cellSpursTasksetSetExceptionEventHandler(vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetExceptionEventHandler> handler, vm::ptr<u64> arg);
s32 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr<CellSpursTaskset> taskset);
s32 cellSpursLookUpTasksetAddress(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id);
s32 cellSpursLookUpTasksetAddress(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id);
s32 cellSpursTasksetGetSpursAddress(vm::cptr<CellSpursTaskset> taskset, vm::ptr<u32> spurs);
s32 cellSpursGetTasksetInfo();
s32 _cellSpursTasksetAttributeInitialize(vm::ptr<CellSpursTasksetAttribute> attribute, u32 revision, u32 sdk_version, u64 args, vm::cptr<u8> priority, u32 max_contention);
@ -154,9 +154,9 @@ s32 _cellSpursTasksetAttributeInitialize(vm::ptr<CellSpursTasksetAttribute> attr
// SPURS task functions
//
s32 spursCreateTask(vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> task_id, vm::cptr<void> elf, vm::cptr<void> context, u32 size, vm::ptr<CellSpursTaskLsPattern> ls_pattern, vm::ptr<CellSpursTaskArgument> arg);
s32 spursTaskStart(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId);
s32 cellSpursCreateTask(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> taskId, vm::cptr<void> elf, vm::cptr<void> context, u32 size, vm::ptr<CellSpursTaskLsPattern> lsPattern, vm::ptr<CellSpursTaskArgument> argument);
s32 _cellSpursSendSignal(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId);
s32 spursTaskStart(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, u32 taskId);
s32 cellSpursCreateTask(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> taskId, vm::cptr<void> elf, vm::cptr<void> context, u32 size, vm::ptr<CellSpursTaskLsPattern> lsPattern, vm::ptr<CellSpursTaskArgument> argument);
s32 _cellSpursSendSignal(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, u32 taskId);
s32 cellSpursCreateTaskWithAttribute();
s32 cellSpursTaskExitCodeGet();
s32 cellSpursTaskExitCodeInitialize();
@ -178,11 +178,11 @@ s32 cellSpursCreateTask2WithBinInfo();
//
s32 _cellSpursEventFlagInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursEventFlag> eventFlag, u32 flagClearMode, u32 flagDirection);
s32 cellSpursEventFlagClear(vm::ptr<CellSpursEventFlag> eventFlag, u16 bits);
s32 cellSpursEventFlagSet(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, u16 bits);
s32 spursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode, u32 block);
s32 cellSpursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
s32 cellSpursEventFlagTryWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag);
s32 cellSpursEventFlagSet(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, u16 bits);
s32 spursEventFlagWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode, u32 block);
s32 cellSpursEventFlagWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
s32 cellSpursEventFlagTryWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag);
s32 cellSpursEventFlagDetachLv2EventQueue(vm::ptr<CellSpursEventFlag> eventFlag);
s32 cellSpursEventFlagGetDirection(vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u32> direction);
s32 cellSpursEventFlagGetClearMode(vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u32> clear_mode);
@ -281,9 +281,9 @@ bool spursIsLibProfLoaded()
//----------------------------------------------------------------------------
/// Create an LV2 event queue and attach it to the SPURS instance
s32 spursCreateLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<u32> queueId, vm::ptr<u8> port, s32 size, vm::cptr<char> name)
s32 spursCreateLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32> queueId, vm::ptr<u8> port, s32 size, vm::cptr<char> name)
{
vm::stackvar<sys_event_queue_attribute_t> attr(CPU);
vm::stackvar<sys_event_queue_attribute_t> attr(ppu);
auto sys_event_queue_attribute_initialize = [](vm::ptr<sys_event_queue_attribute_t> attr)
{
@ -299,8 +299,8 @@ s32 spursCreateLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<u
return rc;
}
vm::stackvar<u8> _port(CPU);
if (s32 rc = spursAttachLv2EventQueue(CPU, spurs, *queueId, _port, 1 /*isDynamic*/, true /*spursCreated*/))
vm::stackvar<u8> _port(ppu);
if (s32 rc = spursAttachLv2EventQueue(ppu, spurs, *queueId, _port, 1 /*isDynamic*/, true /*spursCreated*/))
{
sys_event_queue_destroy(*queueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
}
@ -310,7 +310,7 @@ s32 spursCreateLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<u
}
/// Attach an LV2 event queue to the SPURS instance
s32 spursAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool spursCreated)
s32 spursAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic, bool spursCreated)
{
if (!spurs || !port)
{
@ -350,7 +350,7 @@ s32 spursAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 queue
portMask |= 1ull << (i);
}
vm::stackvar<u8> connectedPort(CPU);
vm::stackvar<u8> connectedPort(ppu);
if (s32 res = sys_spu_thread_group_connect_event_all_threads(spurs->spuTG, queue, portMask, connectedPort))
{
if (res == CELL_EISCONN)
@ -412,9 +412,9 @@ s32 spursDetachLv2EventQueue(vm::ptr<CellSpurs> spurs, u8 spuPort, bool spursCre
}
/// Wait until a workload in the SPURS instance becomes ready
void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
void spursHandlerWaitReady(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
if (s32 rc = sys_lwmutex_lock(CPU, spurs.of(&CellSpurs::mutex), 0))
if (s32 rc = sys_lwmutex_lock(ppu, spurs.of(&CellSpurs::mutex), 0))
{
throw EXCEPTION("sys_lwmutex_lock() failed (0x%x)", rc);
}
@ -427,12 +427,12 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
{
extern u32 g_ppu_func_index__sys_lwmutex_unlock; // test
if (s32 rc = CALL_FUNC(CPU, sys_lwmutex_unlock, CPU, spurs.of(&CellSpurs::mutex)))
if (s32 rc = CALL_FUNC(ppu, sys_lwmutex_unlock, ppu, spurs.of(&CellSpurs::mutex)))
{
throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc);
}
sys_ppu_thread_exit(CPU, 0);
sys_ppu_thread_exit(ppu, 0);
}
// Find a runnable workload
@ -487,7 +487,7 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
spurs->handlerWaiting.store(1);
if (spurs->handlerDirty.load() == 0)
{
if (s32 rc = sys_lwcond_wait(CPU, spurs.of(&CellSpurs::cond), 0))
if (s32 rc = sys_lwcond_wait(ppu, spurs.of(&CellSpurs::cond), 0))
{
throw EXCEPTION("sys_lwcond_wait() failed (0x%x)", rc);
}
@ -497,20 +497,20 @@ void spursHandlerWaitReady(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
}
// If we reach here then a runnable workload was found
if (s32 rc = sys_lwmutex_unlock(CPU, spurs.of(&CellSpurs::mutex)))
if (s32 rc = sys_lwmutex_unlock(ppu, spurs.of(&CellSpurs::mutex)))
{
throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc);
}
}
/// Entry point of the SPURS handler thread. This thread is responsible for starting the SPURS SPU thread group.
void spursHandlerEntry(PPUThread& CPU)
void spursHandlerEntry(PPUThread& ppu)
{
auto spurs = vm::ptr<CellSpurs>::make(VM_CAST(CPU.GPR[3]));
auto spurs = vm::ptr<CellSpurs>::make(VM_CAST(ppu.GPR[3]));
if (spurs->flags & SAF_UNKNOWN_FLAG_30)
{
sys_ppu_thread_exit(CPU, 0);
sys_ppu_thread_exit(ppu, 0);
}
while (true)
@ -519,7 +519,7 @@ void spursHandlerEntry(PPUThread& CPU)
if (spurs->flags1 & SF1_EXIT_IF_NO_WORK)
{
spursHandlerWaitReady(CPU, spurs);
spursHandlerWaitReady(ppu, spurs);
}
if (s32 rc = sys_spu_thread_group_start(spurs->spuTG))
@ -531,7 +531,7 @@ void spursHandlerEntry(PPUThread& CPU)
{
if (rc == CELL_ESTAT)
{
sys_ppu_thread_exit(CPU, 0);
sys_ppu_thread_exit(ppu, 0);
}
throw EXCEPTION("sys_spu_thread_group_join() failed (0x%x)", rc);
@ -544,7 +544,7 @@ void spursHandlerEntry(PPUThread& CPU)
throw EXCEPTION("Unexpected handlerExiting value (false)");
}
sys_ppu_thread_exit(CPU, 0);
sys_ppu_thread_exit(ppu, 0);
}
}
}
@ -558,7 +558,7 @@ s32 spursCreateHandler(vm::ptr<CellSpurs> spurs, u32 ppuPriority)
}
/// Invoke event handlers
s32 spursInvokeEventHandlers(PPUThread& CPU, vm::ptr<CellSpurs::EventPortMux> eventPortMux)
s32 spursInvokeEventHandlers(PPUThread& ppu, vm::ptr<CellSpurs::EventPortMux> eventPortMux)
{
if (eventPortMux->reqPending.exchange(0).data())
{
@ -566,7 +566,7 @@ s32 spursInvokeEventHandlers(PPUThread& CPU, vm::ptr<CellSpurs::EventPortMux> ev
for (auto node = handlerList; node; node = node->next)
{
node->handler(CPU, eventPortMux, node->data);
node->handler(ppu, eventPortMux, node->data);
}
}
@ -574,7 +574,7 @@ s32 spursInvokeEventHandlers(PPUThread& CPU, vm::ptr<CellSpurs::EventPortMux> ev
}
// Invoke workload shutdown completion callbacks
s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 wid)
s32 spursWakeUpShutdownCompletionWaiter(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 wid)
{
if (!spurs)
{
@ -608,7 +608,7 @@ s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs
if (wklF.hook)
{
wklF.hook(CPU, spurs, wid, wklF.hookArg);
wklF.hook(ppu, spurs, wid, wklF.hookArg);
assert(wklEvent.load() & 0x01);
assert(wklEvent.load() & 0x02);
@ -627,28 +627,28 @@ s32 spursWakeUpShutdownCompletionWaiter(PPUThread& CPU, vm::ptr<CellSpurs> spurs
}
/// Entry point of the SPURS event helper thread
void spursEventHelperEntry(PPUThread& CPU)
void spursEventHelperEntry(PPUThread& ppu)
{
const auto spurs = vm::ptr<CellSpurs>::make(VM_CAST(CPU.GPR[3]));
const auto spurs = vm::ptr<CellSpurs>::make(VM_CAST(ppu.GPR[3]));
bool terminate = false;
vm::stackvar<sys_event_t> eventArray(CPU, sizeof32(sys_event_t) * 8);
vm::stackvar<be_t<u32>> count(CPU);
vm::stackvar<sys_event_t> eventArray(ppu, sizeof32(sys_event_t) * 8);
vm::stackvar<be_t<u32>> count(ppu);
vm::ptr<sys_event_t> events = eventArray;
while (!terminate)
{
if (s32 rc = sys_event_queue_receive(CPU, spurs->eventQueue, vm::null, 0 /*timeout*/))
if (s32 rc = sys_event_queue_receive(ppu, spurs->eventQueue, vm::null, 0 /*timeout*/))
{
throw EXCEPTION("sys_event_queue_receive() failed (0x%x)", rc);
}
const u64 event_src = CPU.GPR[4];
const u64 event_data1 = CPU.GPR[5];
const u64 event_data2 = CPU.GPR[6];
const u64 event_data3 = CPU.GPR[7];
const u64 event_src = ppu.GPR[4];
const u64 event_data1 = ppu.GPR[5];
const u64 event_data2 = ppu.GPR[6];
const u64 event_data3 = ppu.GPR[7];
if (event_src == SYS_SPU_THREAD_EVENT_EXCEPTION_KEY)
{
@ -691,7 +691,7 @@ void spursEventHelperEntry(PPUThread& CPU)
{
if (shutdownMask & (0x80000000u >> wid))
{
if (s32 rc = spursWakeUpShutdownCompletionWaiter(CPU, spurs, wid))
if (s32 rc = spursWakeUpShutdownCompletionWaiter(ppu, spurs, wid))
{
throw EXCEPTION("spursWakeUpShutdownCompletionWaiter() failed (0x%x)", rc);
}
@ -699,7 +699,7 @@ void spursEventHelperEntry(PPUThread& CPU)
if ((spurs->flags1 & SF1_32_WORKLOADS) && (shutdownMask & (0x8000 >> wid)))
{
if (s32 rc = spursWakeUpShutdownCompletionWaiter(CPU, spurs, wid + 0x10))
if (s32 rc = spursWakeUpShutdownCompletionWaiter(ppu, spurs, wid + 0x10))
{
throw EXCEPTION("spursWakeUpShutdownCompletionWaiter() failed (0x%x)", rc);
}
@ -715,7 +715,7 @@ void spursEventHelperEntry(PPUThread& CPU)
}
else if (data0 == 3)
{
if (s32 rc = spursInvokeEventHandlers(CPU, spurs.of(&CellSpurs::eventPortMux)))
if (s32 rc = spursInvokeEventHandlers(ppu, spurs.of(&CellSpurs::eventPortMux)))
{
throw EXCEPTION("spursInvokeEventHandlers() failed (0x%x)", rc);
}
@ -729,12 +729,12 @@ void spursEventHelperEntry(PPUThread& CPU)
}
/// Create the SPURS event helper thread
s32 spursCreateSpursEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 ppuPriority)
s32 spursCreateSpursEventHelper(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 ppuPriority)
{
vm::stackvar<char> evqName(CPU, 8);
vm::stackvar<char> evqName(ppu, 8);
memcpy(evqName.get_ptr(), "_spuPrv", 8);
if (s32 rc = spursCreateLv2EventQueue(CPU, spurs, spurs.of(&CellSpurs::eventQueue), spurs.of(&CellSpurs::spuPort), 0x2A /*size*/, evqName))
if (s32 rc = spursCreateLv2EventQueue(ppu, spurs, spurs.of(&CellSpurs::eventQueue), spurs.of(&CellSpurs::spuPort), 0x2A /*size*/, evqName))
{
return rc;
}
@ -843,7 +843,7 @@ s32 spursFinalizeSpu(vm::ptr<CellSpurs> spurs)
}
/// Stop the event helper thread
s32 spursStopEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
s32 spursStopEventHelper(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
if (spurs->ppu1 == 0xFFFFFFFF)
{
@ -855,7 +855,7 @@ s32 spursStopEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
return CELL_SPURS_CORE_ERROR_STAT;
}
if (sys_ppu_thread_join(CPU, (u32)spurs->ppu1, vm::stackvar<be_t<u64>>(CPU)) != CELL_OK)
if (sys_ppu_thread_join(ppu, (u32)spurs->ppu1, vm::stackvar<be_t<u64>>(ppu)) != CELL_OK)
{
return CELL_SPURS_CORE_ERROR_STAT;
}
@ -886,19 +886,19 @@ s32 spursStopEventHelper(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
}
/// Signal to the SPURS handler thread
s32 spursSignalToHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
s32 spursSignalToHandlerThread(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
if (s32 rc = sys_lwmutex_lock(CPU, spurs.of(&CellSpurs::mutex), 0 /* forever */))
if (s32 rc = sys_lwmutex_lock(ppu, spurs.of(&CellSpurs::mutex), 0 /* forever */))
{
throw EXCEPTION("sys_lwmutex_lock() failed (0x%x)", rc);
}
if (s32 rc = sys_lwcond_signal(CPU, spurs.of(&CellSpurs::cond)))
if (s32 rc = sys_lwcond_signal(ppu, spurs.of(&CellSpurs::cond)))
{
throw EXCEPTION("sys_lwcond_signal() failed (0x%x)", rc);
}
if (s32 rc = sys_lwmutex_unlock(CPU, spurs.of(&CellSpurs::mutex)))
if (s32 rc = sys_lwmutex_unlock(ppu, spurs.of(&CellSpurs::mutex)))
{
throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc);
}
@ -907,14 +907,14 @@ s32 spursSignalToHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
}
/// Join the SPURS handler thread
s32 spursJoinHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
s32 spursJoinHandlerThread(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
if (spurs->ppu0 == 0xFFFFFFFF)
{
return CELL_SPURS_CORE_ERROR_STAT;
}
if (s32 rc = sys_ppu_thread_join(CPU, (u32)spurs->ppu0, vm::stackvar<be_t<u64>>(CPU)))
if (s32 rc = sys_ppu_thread_join(ppu, (u32)spurs->ppu0, vm::stackvar<be_t<u64>>(ppu)))
{
throw EXCEPTION("sys_ppu_thread_join() failed (0x%x)", rc);
}
@ -925,7 +925,7 @@ s32 spursJoinHandlerThread(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
/// Initialise SPURS
s32 spursInit(
PPUThread& CPU,
PPUThread& ppu,
vm::ptr<CellSpurs> spurs,
u32 revision,
u32 sdkVersion,
@ -940,17 +940,17 @@ s32 spursInit(
u32 swlMaxSpu,
u32 swlIsPreem)
{
vm::stackvar<be_t<u32>> sem(CPU);
vm::stackvar<sys_semaphore_attribute_t> semAttr(CPU);
vm::stackvar<sys_lwcond_attribute_t> lwCondAttr(CPU);
vm::stackvar<sys_lwmutex_attribute_t> lwMutexAttr(CPU);
vm::stackvar<be_t<u32>> spuTgId(CPU);
vm::stackvar<char> spuTgName(CPU, 128);
vm::stackvar<sys_spu_thread_group_attribute> spuTgAttr(CPU);
vm::stackvar<sys_spu_thread_argument> spuThArgs(CPU);
vm::stackvar<be_t<u32>> spuThreadId(CPU);
vm::stackvar<sys_spu_thread_attribute> spuThAttr(CPU);
vm::stackvar<char> spuThName(CPU, 128);
vm::stackvar<be_t<u32>> sem(ppu);
vm::stackvar<sys_semaphore_attribute_t> semAttr(ppu);
vm::stackvar<sys_lwcond_attribute_t> lwCondAttr(ppu);
vm::stackvar<sys_lwmutex_attribute_t> lwMutexAttr(ppu);
vm::stackvar<be_t<u32>> spuTgId(ppu);
vm::stackvar<char> spuTgName(ppu, 128);
vm::stackvar<sys_spu_thread_group_attribute> spuTgAttr(ppu);
vm::stackvar<sys_spu_thread_argument> spuThArgs(ppu);
vm::stackvar<be_t<u32>> spuThreadId(ppu);
vm::stackvar<sys_spu_thread_attribute> spuThAttr(ppu);
vm::stackvar<char> spuThName(ppu, 128);
if (!spurs)
{
@ -1167,7 +1167,7 @@ s32 spursInit(
if (flags & SAF_SPU_PRINTF_ENABLED)
{
// spu_printf: attach group
if (!spu_printf_agcb || spu_printf_agcb(CPU, spurs->spuTG) != CELL_OK)
if (!spu_printf_agcb || spu_printf_agcb(ppu, spurs->spuTG) != CELL_OK)
{
// remove flag if failed
spurs->flags &= ~SAF_SPU_PRINTF_ENABLED;
@ -1197,7 +1197,7 @@ s32 spursInit(
memcpy(lwCondAttr->name, "_spuPrv", 8);
if (s32 rc = sys_lwcond_create(lwCond, lwMutex, lwCondAttr))
{
sys_lwmutex_destroy(CPU, lwMutex);
sys_lwmutex_destroy(ppu, lwMutex);
spursFinalizeSpu(spurs);
return rollback(), rc;
}
@ -1211,10 +1211,10 @@ s32 spursInit(
spurs->ppuPriority = ppuPriority;
// Create the SPURS event helper thread
if (s32 rc = spursCreateSpursEventHelper(CPU, spurs, ppuPriority))
if (s32 rc = spursCreateSpursEventHelper(ppu, spurs, ppuPriority))
{
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(CPU, lwMutex);
sys_lwmutex_destroy(ppu, lwMutex);
spursFinalizeSpu(spurs);
return rollback(), rc;
}
@ -1222,9 +1222,9 @@ s32 spursInit(
// Create the SPURS handler thread
if (s32 rc = spursCreateHandler(spurs, ppuPriority))
{
spursStopEventHelper(CPU, spurs);
spursStopEventHelper(ppu, spurs);
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(CPU, lwMutex);
sys_lwmutex_destroy(ppu, lwMutex);
spursFinalizeSpu(spurs);
return rollback(), rc;
}
@ -1232,11 +1232,11 @@ s32 spursInit(
// Enable SPURS exception handler
if (s32 rc = cellSpursEnableExceptionEventHandler(spurs, true /*enable*/))
{
spursSignalToHandlerThread(CPU, spurs);
spursJoinHandlerThread(CPU, spurs);
spursStopEventHelper(CPU, spurs);
spursSignalToHandlerThread(ppu, spurs);
spursJoinHandlerThread(ppu, spurs);
spursStopEventHelper(ppu, spurs);
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(CPU, lwMutex);
sys_lwmutex_destroy(ppu, lwMutex);
spursFinalizeSpu(spurs);
return rollback(), rc;
}
@ -1259,22 +1259,22 @@ s32 spursInit(
}
else if (flags & SAF_EXIT_IF_NO_WORK)
{
return cellSpursWakeUp(CPU, spurs);
return cellSpursWakeUp(ppu, spurs);
}
return CELL_OK;
}
/// Initialise SPURS
s32 cellSpursInitialize(PPUThread& CPU, vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork)
s32 cellSpursInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork)
{
cellSpurs.Warning("cellSpursInitialize(spurs=*0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs, nSpus, spuPriority, ppuPriority, exitIfNoWork);
return spursInit(CPU, spurs, 0, 0, nSpus, spuPriority, ppuPriority, exitIfNoWork ? SAF_EXIT_IF_NO_WORK : SAF_NONE, vm::null, 0, 0, vm::null, 0, 0);
return spursInit(ppu, spurs, 0, 0, nSpus, spuPriority, ppuPriority, exitIfNoWork ? SAF_EXIT_IF_NO_WORK : SAF_NONE, vm::null, 0, 0, vm::null, 0, 0);
}
/// Initialise SPURS
s32 cellSpursInitializeWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr)
s32 cellSpursInitializeWithAttribute(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursInitializeWithAttribute(spurs=*0x%x, attr=*0x%x)", spurs, attr);
@ -1294,7 +1294,7 @@ s32 cellSpursInitializeWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, v
}
return spursInit(
CPU,
ppu,
spurs,
attr->revision,
attr->sdkVersion,
@ -1311,7 +1311,7 @@ s32 cellSpursInitializeWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, v
}
/// Initialise SPURS
s32 cellSpursInitializeWithAttribute2(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr)
s32 cellSpursInitializeWithAttribute2(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::cptr<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursInitializeWithAttribute2(spurs=*0x%x, attr=*0x%x)", spurs, attr);
@ -1331,7 +1331,7 @@ s32 cellSpursInitializeWithAttribute2(PPUThread& CPU, vm::ptr<CellSpurs> spurs,
}
return spursInit(
CPU,
ppu,
spurs,
attr->revision,
attr->sdkVersion,
@ -1745,11 +1745,11 @@ s32 cellSpursSetPreemptionVictimHints(vm::ptr<CellSpurs> spurs, vm::cptr<bool> i
}
/// Attach an LV2 event queue to a SPURS instance
s32 cellSpursAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic)
s32 cellSpursAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic)
{
cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs=*0x%x, queue=0x%x, port=*0x%x, isDynamic=%d)", spurs, queue, port, isDynamic);
return spursAttachLv2EventQueue(CPU, spurs, queue, port, isDynamic, false /*spursCreated*/);
return spursAttachLv2EventQueue(ppu, spurs, queue, port, isDynamic, false /*spursCreated*/);
}
/// Detach an LV2 event queue from a SPURS instance
@ -1860,7 +1860,7 @@ s32 cellSpursGetSpuGuid()
//----------------------------------------------------------------------------
/// Signal SPUs to update trace status
void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs)
void spursTraceStatusUpdate(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
u8 init;
@ -1877,7 +1877,7 @@ void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs)
{
spurs->sysSrvMessage.store(0xFF);
if (s32 rc = sys_semaphore_wait((u32)spurs->semPrv, 0))
if (s32 rc = sys_semaphore_wait(ppu, (u32)spurs->semPrv, 0))
{
throw EXCEPTION("sys_semaphore_wait() failed (0x%x)", rc);
}
@ -1885,7 +1885,7 @@ void spursTraceStatusUpdate(vm::ptr<CellSpurs> spurs)
}
/// Initialize SPURS trace
s32 spursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode, u32 updateStatus)
s32 spursTraceInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode, u32 updateStatus)
{
if (!spurs || !buffer)
{
@ -1929,14 +1929,14 @@ s32 spursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> b
spurs->sysSrvTraceControl = 0;
if (updateStatus)
{
spursTraceStatusUpdate(spurs);
spursTraceStatusUpdate(ppu, spurs);
}
return CELL_OK;
}
/// Initialize SPURS trace
s32 cellSpursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode)
s32 cellSpursTraceInitialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInfo> buffer, u32 size, u32 mode)
{
cellSpurs.Warning("cellSpursTraceInitialize(spurs=*0x%x, buffer=*0x%x, size=0x%x, mode=0x%x)", spurs, buffer, size, mode);
@ -1945,11 +1945,11 @@ s32 cellSpursTraceInitialize(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTraceInf
return CELL_SPURS_CORE_ERROR_STAT;
}
return spursTraceInitialize(spurs, buffer, size, mode, 1);
return spursTraceInitialize(ppu, spurs, buffer, size, mode, 1);
}
/// Finalize SPURS trace
s32 cellSpursTraceFinalize(vm::ptr<CellSpurs> spurs)
s32 cellSpursTraceFinalize(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursTraceFinalize(spurs=*0x%x)", spurs);
@ -1971,12 +1971,12 @@ s32 cellSpursTraceFinalize(vm::ptr<CellSpurs> spurs)
spurs->sysSrvTraceControl = 0;
spurs->traceMode = 0;
spurs->traceBuffer = vm::null;
spursTraceStatusUpdate(spurs);
spursTraceStatusUpdate(ppu, spurs);
return CELL_OK;
}
/// Start SPURS trace
s32 spursTraceStart(vm::ptr<CellSpurs> spurs, u32 updateStatus)
s32 spursTraceStart(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 updateStatus)
{
if (!spurs)
{
@ -1996,14 +1996,14 @@ s32 spursTraceStart(vm::ptr<CellSpurs> spurs, u32 updateStatus)
spurs->sysSrvTraceControl = 1;
if (updateStatus)
{
spursTraceStatusUpdate(spurs);
spursTraceStatusUpdate(ppu, spurs);
}
return CELL_OK;
}
/// Start SPURS trace
s32 cellSpursTraceStart(vm::ptr<CellSpurs> spurs)
s32 cellSpursTraceStart(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursTraceStart(spurs=*0x%x)", spurs);
@ -2017,11 +2017,11 @@ s32 cellSpursTraceStart(vm::ptr<CellSpurs> spurs)
return CELL_SPURS_CORE_ERROR_ALIGN;
}
return spursTraceStart(spurs, spurs->traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
return spursTraceStart(ppu, spurs, spurs->traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
}
/// Stop SPURS trace
s32 spursTraceStop(vm::ptr<CellSpurs> spurs, u32 updateStatus)
s32 spursTraceStop(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 updateStatus)
{
if (!spurs)
{
@ -2041,14 +2041,14 @@ s32 spursTraceStop(vm::ptr<CellSpurs> spurs, u32 updateStatus)
spurs->sysSrvTraceControl = 2;
if (updateStatus)
{
spursTraceStatusUpdate(spurs);
spursTraceStatusUpdate(ppu, spurs);
}
return CELL_OK;
}
/// Stop SPURS trace
s32 cellSpursTraceStop(vm::ptr<CellSpurs> spurs)
s32 cellSpursTraceStop(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursTraceStop(spurs=*0x%x)", spurs);
@ -2062,7 +2062,7 @@ s32 cellSpursTraceStop(vm::ptr<CellSpurs> spurs)
return CELL_SPURS_CORE_ERROR_ALIGN;
}
return spursTraceStop(spurs, spurs->traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
return spursTraceStop(ppu, spurs, spurs->traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP);
}
//----------------------------------------------------------------------------
@ -2384,7 +2384,7 @@ s32 cellSpursRemoveWorkload()
}
/// Activate the SPURS kernel
s32 cellSpursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
s32 cellSpursWakeUp(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursWakeUp(spurs=*0x%x)", spurs);
@ -2407,7 +2407,7 @@ s32 cellSpursWakeUp(PPUThread& CPU, vm::ptr<CellSpurs> spurs)
if (spurs->handlerWaiting.load())
{
spursSignalToHandlerThread(CPU, spurs);
spursSignalToHandlerThread(ppu, spurs);
}
return CELL_OK;
@ -2761,7 +2761,7 @@ s32 cellSpursEventFlagClear(vm::ptr<CellSpursEventFlag> eventFlag, u16 bits)
}
/// Set a SPURS event flag
s32 cellSpursEventFlagSet(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, u16 bits)
s32 cellSpursEventFlagSet(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, u16 bits)
{
cellSpurs.Warning("cellSpursEventFlagSet(eventFlag=*0x%x, bits=0x%x)", eventFlag, bits);
@ -2867,17 +2867,17 @@ s32 cellSpursEventFlagSet(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag,
if (pendingRecv & (0x8000 >> i))
{
eventFlag->pendingRecvTaskEvents[i] = pendingRecvTaskEvents[i];
vm::stackvar<vm::bptr<CellSpursTaskset>> taskset(CPU);
vm::stackvar<vm::bptr<CellSpursTaskset>> taskset(ppu);
if (eventFlag->isIwl)
{
cellSpursLookUpTasksetAddress(CPU, vm::ptr<CellSpurs>::make((u32)eventFlag->addr), taskset, eventFlag->waitingTaskWklId[i]);
cellSpursLookUpTasksetAddress(ppu, vm::ptr<CellSpurs>::make((u32)eventFlag->addr), taskset, eventFlag->waitingTaskWklId[i]);
}
else
{
taskset->set((u32)eventFlag->addr);
}
auto rc = _cellSpursSendSignal(CPU, taskset.value(), eventFlag->waitingTaskId[i]);
auto rc = _cellSpursSendSignal(ppu, taskset.value(), eventFlag->waitingTaskId[i]);
if (rc == CELL_SPURS_TASK_ERROR_INVAL || rc == CELL_SPURS_TASK_ERROR_STAT)
{
return CELL_SPURS_TASK_ERROR_FATAL;
@ -2895,7 +2895,7 @@ s32 cellSpursEventFlagSet(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag,
}
/// Wait for SPURS event flag
s32 spursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode, u32 block)
s32 spursEventFlagWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode, u32 block)
{
if (!eventFlag || !mask)
{
@ -3033,7 +3033,7 @@ s32 spursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm
if (recv)
{
// Block till something happens
if (s32 rc = sys_event_queue_receive(CPU, eventFlag->eventQueueId, vm::null, 0))
if (s32 rc = sys_event_queue_receive(ppu, eventFlag->eventQueueId, vm::null, 0))
{
throw EXCEPTION("sys_event_queue_receive() failed (0x%x)", rc);
}
@ -3053,23 +3053,23 @@ s32 spursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm
}
/// Wait for SPURS event flag
s32 cellSpursEventFlagWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode)
s32 cellSpursEventFlagWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode)
{
cellSpurs.Warning("cellSpursEventFlagWait(eventFlag=*0x%x, mask=*0x%x, mode=%d)", eventFlag, mask, mode);
return spursEventFlagWait(CPU, eventFlag, mask, mode, 1 /*block*/);
return spursEventFlagWait(ppu, eventFlag, mask, mode, 1 /*block*/);
}
/// Check SPURS event flag
s32 cellSpursEventFlagTryWait(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode)
s32 cellSpursEventFlagTryWait(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode)
{
cellSpurs.Warning("cellSpursEventFlagTryWait(eventFlag=*0x%x, mask=*0x%x, mode=0x%x)", eventFlag, mask, mode);
return spursEventFlagWait(CPU, eventFlag, mask, mode, 0 /*block*/);
return spursEventFlagWait(ppu, eventFlag, mask, mode, 0 /*block*/);
}
/// Attach an LV2 event queue to a SPURS event flag
s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpursEventFlag> eventFlag)
s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& ppu, vm::ptr<CellSpursEventFlag> eventFlag)
{
cellSpurs.Warning("cellSpursEventFlagAttachLv2EventQueue(eventFlag=*0x%x)", eventFlag);
@ -3104,9 +3104,9 @@ s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpursEvent
spurs = taskset->spurs;
}
vm::stackvar<be_t<u32>> eventQueueId(CPU);
vm::stackvar<u8> port(CPU);
vm::stackvar<char> evqName(CPU, 8);
vm::stackvar<be_t<u32>> eventQueueId(ppu);
vm::stackvar<u8> port(ppu);
vm::stackvar<char> evqName(ppu, 8);
memcpy(evqName.get_ptr(), "_spuEvF", 8);
auto failure = [](s32 rc) -> s32
@ -3115,7 +3115,7 @@ s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpursEvent
return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF));
};
if (s32 rc = spursCreateLv2EventQueue(CPU, spurs, eventQueueId, port, 1, evqName))
if (s32 rc = spursCreateLv2EventQueue(ppu, spurs, eventQueueId, port, 1, evqName))
{
return failure(rc);
}
@ -3128,7 +3128,7 @@ s32 cellSpursEventFlagAttachLv2EventQueue(PPUThread& CPU, vm::ptr<CellSpursEvent
if (eventFlag->direction == CELL_SPURS_EVENT_FLAG_ANY2ANY)
{
vm::stackvar<be_t<u32>> eventPortId(CPU);
vm::stackvar<be_t<u32>> eventPortId(ppu);
s32 rc = sys_event_port_create(eventPortId, SYS_EVENT_PORT_LOCAL, 0);
if (rc == CELL_OK)
@ -3374,7 +3374,7 @@ s32 cellSpursQueueGetDirection()
return CELL_OK;
}
s32 spursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 max_contention, vm::cptr<char> name, u32 size, s32 enable_clear_ls)
s32 spursCreateTaskset(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 max_contention, vm::cptr<char> name, u32 size, s32 enable_clear_ls)
{
if (!spurs || !taskset)
{
@ -3393,7 +3393,7 @@ s32 spursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpu
taskset->enable_clear_ls = enable_clear_ls > 0 ? 1 : 0;
taskset->size = size;
vm::stackvar<CellSpursWorkloadAttribute> wkl_attr(CPU);
vm::stackvar<CellSpursWorkloadAttribute> wkl_attr(ppu);
_cellSpursWorkloadAttributeInitialize(wkl_attr, 1 /*revision*/, 0x33 /*sdk_version*/, vm::cptr<void>::make(SPURS_IMG_ADDR_TASKSET_PM), 0x1E40 /*pm_size*/,
taskset.addr(), priority, 8 /*min_contention*/, max_contention);
// TODO: Check return code
@ -3404,7 +3404,7 @@ s32 spursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpu
// TODO: cellSpursWorkloadAttributeSetShutdownCompletionEventHook(wkl_attr, hook, taskset);
// TODO: Check return code
vm::stackvar<be_t<u32>> wid(CPU);
vm::stackvar<be_t<u32>> wid(ppu);
cellSpursAddWorkloadWithAttribute(spurs, wid, wkl_attr);
// TODO: Check return code
@ -3416,7 +3416,7 @@ s32 spursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpu
return CELL_OK;
}
s32 cellSpursCreateTasksetWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute> attr)
s32 cellSpursCreateTasksetWithAttribute(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute> attr)
{
cellSpurs.Warning("cellSpursCreateTasksetWithAttribute(spurs=*0x%x, taskset=*0x%x, attr=*0x%x)", spurs, taskset, attr);
@ -3435,7 +3435,7 @@ s32 cellSpursCreateTasksetWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs
return CELL_SPURS_TASK_ERROR_INVAL;
}
auto rc = spursCreateTaskset(CPU, spurs, taskset, attr->args, attr.of(&CellSpursTasksetAttribute::priority), attr->max_contention, attr->name, attr->taskset_size, attr->enable_clear_ls);
auto rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, attr.of(&CellSpursTasksetAttribute::priority), attr->max_contention, attr->name, attr->taskset_size, attr->enable_clear_ls);
if (attr->taskset_size >= sizeof32(CellSpursTaskset2))
{
@ -3445,11 +3445,11 @@ s32 cellSpursCreateTasksetWithAttribute(PPUThread& CPU, vm::ptr<CellSpurs> spurs
return rc;
}
s32 cellSpursCreateTaskset(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 maxContention)
s32 cellSpursCreateTaskset(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, u64 args, vm::cptr<u8[8]> priority, u32 maxContention)
{
cellSpurs.Warning("cellSpursCreateTaskset(spurs=*0x%x, taskset=*0x%x, args=0x%llx, priority=*0x%x, maxContention=%d)", spurs, taskset, args, priority, maxContention);
return spursCreateTaskset(CPU, spurs, taskset, args, priority, maxContention, vm::null, sizeof32(CellSpursTaskset), 0);
return spursCreateTaskset(ppu, spurs, taskset, args, priority, maxContention, vm::null, sizeof32(CellSpursTaskset), 0);
}
s32 cellSpursJoinTaskset(vm::ptr<CellSpursTaskset> taskset)
@ -3587,7 +3587,7 @@ s32 spursCreateTask(vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> task_id, vm:
return CELL_OK;
}
s32 spursTaskStart(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId)
s32 spursTaskStart(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, u32 taskId)
{
auto pendingReady = taskset->pending_ready.value();
pendingReady._bit[taskId] = true;
@ -3595,7 +3595,7 @@ s32 spursTaskStart(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId
cellSpursSendWorkloadSignal(taskset->spurs, taskset->wid);
if (s32 rc = cellSpursWakeUp(CPU, taskset->spurs))
if (s32 rc = cellSpursWakeUp(ppu, taskset->spurs))
{
if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT)
{
@ -3610,7 +3610,7 @@ s32 spursTaskStart(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId
return CELL_OK;
}
s32 cellSpursCreateTask(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> taskId, vm::cptr<void> elf, vm::cptr<void> context, u32 size, vm::ptr<CellSpursTaskLsPattern> lsPattern, vm::ptr<CellSpursTaskArgument> argument)
s32 cellSpursCreateTask(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> taskId, vm::cptr<void> elf, vm::cptr<void> context, u32 size, vm::ptr<CellSpursTaskLsPattern> lsPattern, vm::ptr<CellSpursTaskArgument> argument)
{
cellSpurs.Warning("cellSpursCreateTask(taskset=*0x%x, taskID=*0x%x, elf=*0x%x, context=*0x%x, size=0x%x, lsPattern=*0x%x, argument=*0x%x)", taskset, taskId, elf, context, size, lsPattern, argument);
@ -3624,14 +3624,14 @@ s32 cellSpursCreateTask(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, vm::p
return CELL_SPURS_TASK_ERROR_ALIGN;
}
vm::stackvar<be_t<u32>> tmpTaskId(CPU);
vm::stackvar<be_t<u32>> tmpTaskId(ppu);
auto rc = spursCreateTask(taskset, tmpTaskId, elf, context, size, lsPattern, argument);
if (rc != CELL_OK)
{
return rc;
}
rc = spursTaskStart(CPU, taskset, tmpTaskId.value());
rc = spursTaskStart(ppu, taskset, tmpTaskId.value());
if (rc != CELL_OK)
{
return rc;
@ -3641,7 +3641,7 @@ s32 cellSpursCreateTask(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, vm::p
return CELL_OK;
}
s32 _cellSpursSendSignal(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32 taskId)
s32 _cellSpursSendSignal(PPUThread& ppu, vm::ptr<CellSpursTaskset> taskset, u32 taskId)
{
if (!taskset)
{
@ -3675,7 +3675,7 @@ s32 _cellSpursSendSignal(PPUThread& CPU, vm::ptr<CellSpursTaskset> taskset, u32
if (shouldSignal)
{
cellSpursSendWorkloadSignal(taskset->spurs, taskset->wid);
auto rc = cellSpursWakeUp(CPU, taskset->spurs);
auto rc = cellSpursWakeUp(ppu, taskset->spurs);
if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT)
{
return CELL_SPURS_TASK_ERROR_STAT;
@ -3847,11 +3847,11 @@ s32 cellSpursTaskGetContextSaveAreaSize()
return CELL_OK;
}
s32 cellSpursCreateTaskset2(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute2> attr)
s32 cellSpursCreateTaskset2(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> taskset, vm::ptr<CellSpursTasksetAttribute2> attr)
{
cellSpurs.Warning("cellSpursCreateTaskset2(spurs=*0x%x, taskset=*0x%x, attr=*0x%x)", spurs, taskset, attr);
vm::stackvar<CellSpursTasksetAttribute2> tmp_attr(CPU);
vm::stackvar<CellSpursTasksetAttribute2> tmp_attr(ppu);
if (!attr)
{
@ -3859,7 +3859,7 @@ s32 cellSpursCreateTaskset2(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::ptr<Ce
_cellSpursTasksetAttribute2Initialize(attr, 0);
}
if (s32 rc = spursCreateTaskset(CPU, spurs, taskset, attr->args, attr.of(&CellSpursTasksetAttribute2::priority), attr->max_contention, attr->name, sizeof32(CellSpursTaskset2), attr->enable_clear_ls))
if (s32 rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, attr.of(&CellSpursTasksetAttribute2::priority), attr->max_contention, attr->name, sizeof32(CellSpursTaskset2), attr->enable_clear_ls))
{
return rc;
}
@ -3956,7 +3956,7 @@ s32 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr<CellSpursTaskset> taskset
return CELL_OK;
}
s32 cellSpursLookUpTasksetAddress(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id)
s32 cellSpursLookUpTasksetAddress(PPUThread& ppu, vm::ptr<CellSpurs> spurs, vm::pptr<CellSpursTaskset> taskset, u32 id)
{
cellSpurs.Warning("cellSpursLookUpTasksetAddress(spurs=*0x%x, taskset=**0x%x, id=0x%x)", spurs, taskset, id);
@ -3965,7 +3965,7 @@ s32 cellSpursLookUpTasksetAddress(PPUThread& CPU, vm::ptr<CellSpurs> spurs, vm::
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
}
vm::stackvar<be_t<u64>> data(CPU);
vm::stackvar<be_t<u64>> data(ppu);
if (s32 rc = cellSpursGetWorkloadData(spurs, data, id))
{
// Convert policy module error code to a task error code

View file

@ -76,7 +76,7 @@ s32 sys_cond_destroy(u32 cond_id)
return CELL_ESRCH;
}
if (!cond->sq.empty() || cond.use_count() > 2)
if (!cond->sq.empty())
{
return CELL_EBUSY;
}
@ -197,7 +197,7 @@ s32 sys_cond_wait(PPUThread& ppu, u32 cond_id, u64 timeout)
// add waiter; protocol is ignored in current implementation
sleep_queue_entry_t waiter(ppu, cond->sq);
// add empty mutex waiter (may be actually set later)
// potential mutex waiter (not added immediately)
sleep_queue_entry_t mutex_waiter(ppu, cond->mutex->sq, defer_sleep);
while (!ppu.unsignal())

View file

@ -80,7 +80,6 @@ s32 sys_mutex_destroy(u32 mutex_id)
return CELL_ESRCH;
}
// assuming that the mutex is locked immediately by another waiting thread when unlocked
if (mutex->owner || mutex->sq.size())
{
return CELL_EBUSY;

View file

@ -5,18 +5,17 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/Cell/PPUThread.h"
#include "sleep_queue.h"
#include "sys_semaphore.h"
SysCallBase sys_semaphore("sys_semaphore");
extern u64 get_system_time();
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
s32 sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
{
sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val);
sys_semaphore.Warning("sys_semaphore_create(sem_id=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem_id, attr, initial_val, max_val);
if (!sem || !attr)
if (!sem_id || !attr)
{
return CELL_EFAULT;
}
@ -29,12 +28,10 @@ s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> at
const u32 protocol = attr->protocol;
switch (protocol)
if (protocol != SYS_SYNC_FIFO && protocol != SYS_SYNC_PRIORITY && protocol != SYS_SYNC_PRIORITY_INHERIT)
{
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT: break;
default: sys_semaphore.Error("sys_semaphore_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL;
sys_semaphore.Error("sys_semaphore_create(): unknown protocol (0x%x)", protocol);
return CELL_EINVAL;
}
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key.data() || attr->flags.data())
@ -43,103 +40,115 @@ s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> at
return CELL_EINVAL;
}
*sem = Emu.GetIdManager().make<lv2_sema_t>(protocol, max_val, attr->name_u64, initial_val);
*sem_id = Emu.GetIdManager().make<lv2_sema_t>(protocol, max_val, attr->name_u64, initial_val);
return CELL_OK;
}
s32 sys_semaphore_destroy(u32 sem)
s32 sys_semaphore_destroy(u32 sem_id)
{
sys_semaphore.Warning("sys_semaphore_destroy(sem=0x%x)", sem);
sys_semaphore.Warning("sys_semaphore_destroy(sem_id=0x%x)", sem_id);
LV2_LOCK;
const auto semaphore = Emu.GetIdManager().get<lv2_sema_t>(sem);
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(sem_id);
if (!semaphore)
if (!sem)
{
return CELL_ESRCH;
}
if (semaphore->waiters)
if (sem->sq.size())
{
return CELL_EBUSY;
}
Emu.GetIdManager().remove<lv2_sema_t>(sem);
Emu.GetIdManager().remove<lv2_sema_t>(sem_id);
return CELL_OK;
}
s32 sys_semaphore_wait(u32 sem, u64 timeout)
s32 sys_semaphore_wait(PPUThread& ppu, u32 sem_id, u64 timeout)
{
sys_semaphore.Log("sys_semaphore_wait(sem=0x%x, timeout=0x%llx)", sem, timeout);
sys_semaphore.Log("sys_semaphore_wait(sem_id=0x%x, timeout=0x%llx)", sem_id, timeout);
const u64 start_time = get_system_time();
LV2_LOCK;
const auto semaphore = Emu.GetIdManager().get<lv2_sema_t>(sem);
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(sem_id);
if (!semaphore)
if (!sem)
{
return CELL_ESRCH;
}
// protocol is ignored in current implementation
semaphore->waiters++;
if (sem->value > 0)
{
sem->value--;
return CELL_OK;
}
while (semaphore->value <= 0)
// add waiter; protocol is ignored in current implementation
sleep_queue_entry_t waiter(ppu, sem->sq);
while (!ppu.unsignal())
{
CHECK_EMU_STATUS;
if (timeout && get_system_time() - start_time > timeout)
if (timeout)
{
semaphore->waiters--;
return CELL_ETIMEDOUT;
const u64 passed = get_system_time() - start_time;
if (passed >= timeout)
{
return CELL_ETIMEDOUT;
}
ppu.cv.wait_for(lv2_lock, std::chrono::microseconds(timeout - passed));
}
else
{
ppu.cv.wait(lv2_lock);
}
semaphore->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
}
semaphore->value--;
semaphore->waiters--;
return CELL_OK;
}
s32 sys_semaphore_trywait(u32 sem)
s32 sys_semaphore_trywait(u32 sem_id)
{
sys_semaphore.Log("sys_semaphore_trywait(sem=0x%x)", sem);
sys_semaphore.Log("sys_semaphore_trywait(sem_id=0x%x)", sem_id);
LV2_LOCK;
const auto semaphore = Emu.GetIdManager().get<lv2_sema_t>(sem);
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(sem_id);
if (!semaphore)
if (!sem)
{
return CELL_ESRCH;
}
if (semaphore->value <= 0 || semaphore->waiters)
if (sem->value <= 0 || sem->sq.size())
{
return CELL_EBUSY;
}
semaphore->value--;
sem->value--;
return CELL_OK;
}
s32 sys_semaphore_post(u32 sem, s32 count)
s32 sys_semaphore_post(u32 sem_id, s32 count)
{
sys_semaphore.Log("sys_semaphore_post(sem=0x%x, count=%d)", sem, count);
sys_semaphore.Log("sys_semaphore_post(sem_id=0x%x, count=%d)", sem_id, count);
LV2_LOCK;
const auto semaphore = Emu.GetIdManager().get<lv2_sema_t>(sem);
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(sem_id);
if (!semaphore)
if (!sem)
{
return CELL_ESRCH;
}
@ -149,43 +158,53 @@ s32 sys_semaphore_post(u32 sem, s32 count)
return CELL_EINVAL;
}
const u64 new_value = semaphore->value + count;
const u64 max_value = semaphore->max + semaphore->waiters;
// get comparable values considering waiting threads
const u64 new_value = sem->value + count;
const u64 max_value = sem->max + sem->sq.size();
if (new_value > max_value)
{
return CELL_EBUSY;
}
semaphore->value += count;
if (semaphore->waiters)
// wakeup as much threads as possible
while (count && !sem->sq.empty())
{
semaphore->cv.notify_all();
count--;
if (!sem->sq.front()->signal())
{
throw EXCEPTION("Thread already signaled");
}
sem->sq.pop_front();
}
// add the rest to the value
sem->value += count;
return CELL_OK;
}
s32 sys_semaphore_get_value(u32 sem, vm::ptr<s32> count)
s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count)
{
sys_semaphore.Log("sys_semaphore_get_value(sem=0x%x, count=*0x%x)", sem, count);
sys_semaphore.Log("sys_semaphore_get_value(sem_id=0x%x, count=*0x%x)", sem_id, count);
LV2_LOCK;
if (!count)
{
return CELL_EFAULT;
}
LV2_LOCK;
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(sem_id);
const auto semaphore = Emu.GetIdManager().get<lv2_sema_t>(sem);
if (!semaphore)
if (!sem)
{
return CELL_ESRCH;
}
*count = std::max<s32>(0, semaphore->value - semaphore->waiters);
*count = sem->value;
return CELL_OK;
}

View file

@ -1,5 +1,7 @@
#pragma once
#include "sleep_queue.h"
namespace vm { using namespace ps3; }
struct sys_semaphore_attribute_t
@ -25,26 +27,26 @@ struct lv2_sema_t
std::atomic<s32> value;
// TODO: use sleep queue, possibly remove condition variable
std::condition_variable cv;
std::atomic<u32> waiters;
sleep_queue_t sq;
lv2_sema_t(u32 protocol, s32 max, u64 name, s32 value)
: protocol(protocol)
, max(max)
, name(name)
, value(value)
, waiters(0)
{
}
};
REG_ID_TYPE(lv2_sema_t, 0x96); // SYS_SEMAPHORE_OBJECT
// Aux
class PPUThread;
// SysCalls
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_destroy(u32 sem);
s32 sys_semaphore_wait(u32 sem, u64 timeout);
s32 sys_semaphore_trywait(u32 sem);
s32 sys_semaphore_post(u32 sem, s32 count);
s32 sys_semaphore_get_value(u32 sem, vm::ptr<s32> count);
s32 sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_destroy(u32 sem_id);
s32 sys_semaphore_wait(PPUThread& ppu, u32 sem_id, u64 timeout);
s32 sys_semaphore_trywait(u32 sem_id);
s32 sys_semaphore_post(u32 sem_id, s32 count);
s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count);

View file

@ -86,7 +86,7 @@ void KernelExplorer::Update()
for (const auto id : Emu.GetIdManager().get_IDs(SYS_SEMAPHORE_OBJECT))
{
const auto sem = Emu.GetIdManager().get<lv2_sema_t>(id);
sprintf(name, "Semaphore: ID = 0x%x '%s', Count = %d, Max Count = %d, Waiters = %d", id, &name64(sem->name), sem->value.load(), sem->max, sem->waiters.load());
sprintf(name, "Semaphore: ID = 0x%x '%s', Count = %d, Max Count = %d, Waiters = %lld", id, &name64(sem->name), sem->value.load(), sem->max, sem->sq.size());
m_tree->AppendItem(node, name);
}
}