/* TODO: This routine is a bit overloaded. * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout * is specified, convert it to microseconds. */ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) { Uint32 *pTimeout; int res; if (sem == NULL) { SDL_SetError("Passed a NULL sem"); return 0; } if (timeout == 0) { res = sceKernelPollSema(sem->semid, 1); if (res < 0) { return SDL_MUTEX_TIMEDOUT; } return 0; } if (timeout == SDL_MUTEX_MAXWAIT) { pTimeout = NULL; } else { timeout *= 1000; /* Convert to microseconds. */ pTimeout = &timeout; } res = sceKernelWaitSema(sem->semid, 1, pTimeout); switch (res) { case SCE_KERNEL_ERROR_OK: return 0; case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return SDL_MUTEX_TIMEDOUT; default: return SDL_SetError("sceKernelWaitSema() failed"); } }
void checkSema(int doDispatch) { SceUID sema = sceKernelCreateSema("sema", 0, 0, 1, NULL); dispatchCheckpoint("sceKernelCreateSema: %08x", sema >= 0 ? 1 : sema); dispatchCheckpoint("sceKernelSignalSema: %08x", sceKernelSignalSema(sema, 1)); dispatchCheckpoint("sceKernelWaitSema: %08x", sceKernelWaitSema(sema, 1, NULL)); dispatchCheckpoint("sceKernelWaitSema too much: %08x", sceKernelWaitSema(sema, 9, NULL)); dispatchCheckpoint("sceKernelDeleteSema: %08x", sceKernelDeleteSema(sema)); sema = sceKernelCreateSema("test", 0, 1, 2, NULL); dispatchCheckpoint("sceKernelCreateSema: %08x", sema >= 0 ? 1 : sema); startLockThreadSema(sema); int state; if (doDispatch) { ++ignoreResched; state = sceKernelSuspendDispatchThread(); dispatchCheckpoint("sceKernelSuspendDispatchThread: %08x", state); } SceUInt timeout = 300; dispatchCheckpoint("sceKernelWaitSema: %08x", sceKernelWaitSema(sema, 1, &timeout)); dispatchCheckpoint("sceKernelSignalSema: %08x", sceKernelSignalSema(sema, 1)); if (doDispatch) { dispatchCheckpoint("sceKernelResumeDispatchThread: %08x", sceKernelResumeDispatchThread(state)); --ignoreResched; } endLockThreadSema(sema); dispatchCheckpoint("sceKernelPollSema: %08x", sceKernelPollSema(sema, 1)); dispatchCheckpoint("sceKernelDeleteSema: %08x", sceKernelDeleteSema(sema)); }
SceUID hook_sceKernelCreateThread(const char *name, SceKernelThreadEntry entry, int initPriority, SceSize stackSize, SceUInt attr, int cpuAffinityMask, const SceKernelThreadOptParam *option) { SceKernelSemaInfo info; globals_t *globals; SceUID uid; int res; globals = getGlobals(); sceKernelLockMutexCB(globals->threadmgrMutex, 1, NULL); res = sceKernelPollSema(globals->threadmgrSema, 1); if (res) goto force; info.size = sizeof(info); res = sceKernelGetSemaInfo(globals->threadmgrSema, &info); if (res) goto force; uid = sceKernelCreateThread(name, hookEntry, initPriority, stackSize, attr, cpuAffinityMask, option); if (uid >= 0) { globals->threadmgrTable[info.currentCount].uid = uid; globals->threadmgrTable[info.currentCount].entry = entry; globals->threadmgrTable[info.currentCount].exitDeleteCb = SCE_KERNEL_ERROR_ERROR; } sceKernelUnlockMutex(globals->threadmgrMutex, 1); return uid; force: sceKernelUnlockMutex(globals->threadmgrMutex, 1); return sceKernelCreateThread(name, entry, initPriority, stackSize, attr, cpuAffinityMask, option); }