Error IOS_DestroySempahore(SemaphoreId id) { auto semaphore = getSemaphore(id); if (!semaphore) { return Error::Invalid; } semaphore->count = 0; semaphore->maxCount = 0; // Add semaphore to the free semaphore linked list. auto index = static_cast<int16_t>(semaphore - phys_addrof(sData->semaphores)); auto prevSemaphoreIndex = sData->lastFreeSemaphoreIndex; if (prevSemaphoreIndex >= 0) { auto prevSemaphore = phys_addrof(sData->semaphores[sData->lastFreeSemaphoreIndex]); prevSemaphore->nextFreeSemaphoreIndex = index; } semaphore->prevFreeSemaphoreIndex = prevSemaphoreIndex; semaphore->nextFreeSemaphoreIndex = int16_t { -1 }; sData->lastFreeSemaphoreIndex = index; if (sData->firstFreeSemaphoreIndex < 0) { sData->firstFreeSemaphoreIndex = index; } internal::wakeupAllThreads(phys_addrof(semaphore->waitThreadQueue), Error::Intr); internal::reschedule(); return Error::Invalid; }
Error IOS_CreateSemaphore(int32_t maxCount, int32_t initialCount) { if (sData->firstFreeSemaphoreIndex < 0) { return Error::Max; } auto semaphore = phys_addrof(sData->semaphores[sData->firstFreeSemaphoreIndex]); auto semaphoreId = sData->firstFreeSemaphoreIndex; // Remove semaphore from free semaphore linked list sData->firstFreeSemaphoreIndex = semaphore->nextFreeSemaphoreIndex; if (semaphore->nextFreeSemaphoreIndex >= 0) { sData->semaphores[semaphore->nextFreeSemaphoreIndex].prevFreeSemaphoreIndex = int16_t { -1 }; } else { sData->lastFreeSemaphoreIndex = int16_t { -1 }; } semaphore->nextFreeSemaphoreIndex = int16_t { -1 }; semaphore->prevFreeSemaphoreIndex = int16_t { -1 }; sData->numCreatedSemaphores++; semaphore->id = static_cast<SemaphoreId>(semaphoreId | (sData->numCreatedSemaphores << 12)); semaphore->count = initialCount; semaphore->maxCount = maxCount; semaphore->pid = internal::getCurrentProcessId(); semaphore->unknown0x04 = nullptr; ThreadQueue_Initialise(phys_addrof(semaphore->waitThreadQueue)); return static_cast<Error>(semaphore->id); }
Error startUsrCfgServiceThread() { // Create message queue auto error = IOS_CreateMessageQueue(phys_addrof(sData->messageBuffer), static_cast<uint32_t>(sData->messageBuffer.size())); if (error < Error::OK) { return error; } sData->messageQueueId = static_cast<MessageQueueId>(error); // Register the device error = mcp::MCP_RegisterResourceManager("/dev/usr_cfg", sData->messageQueueId); if (error < Error::OK) { IOS_DestroyMessageQueue(sData->messageQueueId); return error; } // Create thread error = IOS_CreateThread(&usrCfgServiceThreadEntry, nullptr, phys_addrof(sData->threadStack) + sData->threadStack.size(), static_cast<uint32_t>(sData->threadStack.size()), UCServiceThreadPriority, ThreadFlags::Detached); if (error < Error::OK) { IOS_DestroyMessageQueue(sData->messageQueueId); return error; } sData->threadId = static_cast<ThreadId>(error); kernel::internal::setThreadName(sData->threadId, "UsrCfgServiceThread"); return IOS_StartThread(sData->threadId); }
Error IOS_WaitSemaphore(SemaphoreId id, BOOL tryWait) { auto semaphore = getSemaphore(id); if (!semaphore) { return Error::Invalid; } if (semaphore->count <= 0 && tryWait) { return Error::SemUnavailable; } while (semaphore->count <= 0) { internal::sleepThread(phys_addrof(semaphore->waitThreadQueue)); internal::reschedule(); auto thread = internal::getCurrentThread(); if (thread->context.queueWaitResult != Error::OK) { return thread->context.queueWaitResult; } } semaphore->count -= 1; return Error::OK; }
Error IOS_SignalSempahore(SemaphoreId id) { auto semaphore = getSemaphore(id); if (!semaphore) { return Error::Invalid; } if (semaphore->count < semaphore->maxCount) { semaphore->count += 1; } internal::wakeupOneThread(phys_addrof(semaphore->waitThreadQueue), Error::OK); internal::reschedule(); return Error::OK; }
Error startPpcThread() { // Create thread auto error = IOS_CreateThread(&ppcThreadEntry, nullptr, phys_addrof(sPpcThreadData->threadStack) + sPpcThreadData->threadStack.size(), static_cast<uint32_t>(sPpcThreadData->threadStack.size()), PpcThreadPriority, ThreadFlags::Detached); if (error < Error::OK) { return error; } sPpcThreadData->threadId = static_cast<ThreadId>(error); kernel::internal::setThreadName(sPpcThreadData->threadId, "PpcThread"); return IOS_StartThread(sPpcThreadData->threadId); }