/* * This has to be cancellable, so we can't just call sceKernelWaitThreadEnd. * Instead, poll on this in a loop, like we do for a cancellable semaphore. */ pte_osResult pte_osThreadWaitForEnd(pte_osThreadHandle threadHandle) { pte_osResult osResult; psl1ghtThreadData *pThreadData; u64 result; pThreadData = getThreadData(threadHandle); if (pThreadData == NULL) { sysThreadJoin (threadHandle, &result); osResult = PTE_OS_OK; } else { while (1) { if (pThreadData->ended == 1) { /* Thread has ended */ osResult = PTE_OS_OK; break; } else { s32 count; if (sysSemGetValue (pThreadData->cancelSem, &count) == 0) { if (count > 0) { osResult = PTE_OS_INTERRUPTED; break; } else { /* Nothing found and not timed out yet; let's yield so we're not * in busy loop. */ sysThreadYield (); } } else { osResult = PTE_OS_GENERAL_FAILURE; break; } } } } return osResult; }
/* Returns the current count of the semaphore */ Uint32 SDL_SemValue(SDL_sem * sem) { int32_t count; Uint32 value; value = 0; if (sem) { sysSemGetValue (sem->id, &count); if (count > 0) { value = (Uint32) count; } } return value; }
pte_osResult pte_osThreadCheckCancel(pte_osThreadHandle threadHandle) { psl1ghtThreadData *pThreadData; pte_osResult result; pThreadData = getThreadData(threadHandle); if (pThreadData != NULL) { s32 count; if (sysSemGetValue (pThreadData->cancelSem, &count) == 0) { if (count > 0) { result = PTE_OS_INTERRUPTED; } else { result = PTE_OS_OK; } } else { /* sysSemGetValue returned an error */ result = PTE_OS_GENERAL_FAILURE; } } else { /* For some reason, we couldn't get thread data */ result = PTE_OS_GENERAL_FAILURE; } return result; }
/* * Pend on a semaphore- and allow the pend to be cancelled. * * PS3 OS provides no functionality to asynchronously interrupt a blocked call. We simulte * this by polling on the main semaphore and the cancellation semaphore and sleeping in a loop. */ pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle semHandle, unsigned int *pTimeout) { psl1ghtThreadData *pThreadData; sys_ppu_thread_t threadId; sysThreadGetId (&threadId); pThreadData = getThreadData(threadId); clock_t start_time; s32 result = 0; u64 timeout; unsigned char timeoutEnabled; start_time = clock(); // clock() is in microseconds, timeout as passed in was in milliseconds if (pTimeout == NULL) { timeout = 0; timeoutEnabled = 0; } else { timeout = *pTimeout * 1000; timeoutEnabled = 1; } while (1) { int status; /* Poll semaphore */ status = sysSemTryWait(semHandle); if (status == 0) { /* User semaphore posted to */ result = PTE_OS_OK; break; } else if ((timeoutEnabled) && ((clock() - start_time) > timeout)) { /* Timeout expired */ result = PTE_OS_TIMEOUT; break; } else { if (pThreadData != NULL) { s32 count; s32 osResult; osResult = sysSemGetValue (pThreadData->cancelSem, &count); if (osResult == 0) { if (count > 0) { result = PTE_OS_INTERRUPTED; break; } else { /* Nothing found and not timed out yet; let's yield so we're not * in busy loop. */ sysThreadYield (); } } else { result = PTE_OS_GENERAL_FAILURE; break; } } } } return result; }