void OSDetachThread(OSThread *thread) { OSLockScheduler(); thread->attr |= OSThreadAttributes::Detached; OSUnlockScheduler(); }
void OSCancelThread(OSThread *thread) { bool reschedule = false; OSLockScheduler(); if (thread->requestFlag == OSThreadRequest::Suspend) { OSWakeupThreadWaitForSuspensionNoLock(&thread->suspendQueue, -1); reschedule = true; } if (thread->suspendCounter != 0) { if (thread->cancelState == 0) { OSResumeThreadNoLock(thread, thread->suspendCounter); reschedule = true; } } if (reschedule) { OSRescheduleNoLock(); } thread->suspendCounter = 0; thread->needSuspend = 0; thread->requestFlag = OSThreadRequest::Cancel; OSUnlockScheduler(); if (OSGetCurrentThread() == thread) { OSExitThread(-1); } }
void OSTestThreadCancel() { OSLockScheduler(); OSTestThreadCancelNoLock(); OSUnlockScheduler(); }
void OSSleepTicks(Time ticks) { if (1) { OSTestThreadCancel(); gLog->warn("Ignoring unimplemented OSSleepTicks"); return; } auto thread = OSGetCurrentThread(); OSLockScheduler(); // Create the alarm user data auto data = OSAllocFromSystem<SleepAlarmData>(); data->thread = thread; // Create an alarm to trigger wakeup auto alarm = OSAllocFromSystem<OSAlarm>(); OSCreateAlarm(alarm); OSSetAlarmUserData(alarm, data); OSSetAlarm(alarm, ticks, pSleepAlarmHandler); // Sleep thread OSSleepThreadNoLock(nullptr); OSRescheduleNoLock(); OSFreeToSystem(data); OSFreeToSystem(alarm); OSUnlockScheduler(); }
void OSWakeupThread(OSThreadQueue *queue) { OSLockScheduler(); OSWakeupThreadNoLock(queue); OSUnlockScheduler(); }
/** * Signal the event and wakeup all waiting threads regardless of mode * * This differs to OSSignalEvent only for auto reset mode where it * will wake up all threads instead of just one. * * If there is at least one thread woken up and the alarm is in * auto reset mode then the event value is reset to FALSE. */ void OSSignalEventAll(OSEvent *event) { OSLockScheduler(); assert(event); assert(event->tag == OSEvent::Tag); if (event->value != FALSE) { // Event has already been set OSUnlockScheduler(); return; } // Set event event->value = TRUE; if (!OSIsThreadQueueEmpty(&event->queue)) { if (event->mode == OSEventMode::AutoReset) { // Reset event event->value = FALSE; } // Wakeup all threads OSWakeupThreadNoLock(&event->queue); OSRescheduleNoLock(); } OSUnlockScheduler(); }
void OSClearThreadStackUsage(OSThread *thread) { OSLockScheduler(); thread->attr &= ~OSThreadAttributes::StackUsage; OSUnlockScheduler(); }
/** * Wait for the event value to become TRUE. * * If the event value is already TRUE then this will return immediately, * and will set the event value to FALSE if the event is in auto reset mode. * * If the event value is FALSE then the thread will sleep until the event * is signalled by another thread. */ void OSWaitEvent(OSEvent *event) { OSLockScheduler(); assert(event); assert(event->tag == OSEvent::Tag); if (event->value) { // Event is already set if (event->mode == OSEventMode::AutoReset) { // Reset event event->value = FALSE; } OSUnlockScheduler(); return; } else { // Wait for event to be set OSSleepThreadNoLock(&event->queue); OSRescheduleNoLock(); } OSUnlockScheduler(); }
void OSContinueThread(OSThread *thread) { OSLockScheduler(); OSResumeThreadNoLock(thread, thread->suspendCounter); OSRescheduleNoLock(); OSUnlockScheduler(); }
void OSSleepThread(OSThreadQueue *queue) { OSLockScheduler(); OSSleepThreadNoLock(queue); OSRescheduleNoLock(); OSUnlockScheduler(); }
void OSUnlockMutex(OSMutex *mutex) { OSLockScheduler(); OSUnlockMutexNoLock(mutex); OSTestThreadCancelNoLock(); OSUnlockScheduler(); }
void Processor::reschedule(bool hasSchedulerLock, bool yield) { std::unique_lock<std::mutex> lock { mMutex }; auto core = tCurrentCore; if (!core) { // Ran from host thread return; } auto fiber = core->currentFiber; auto thread = fiber->thread; auto next = peekNextFiberNoLock(core->id); // Priority is 0 = highest, 31 = lowest if (thread->suspendCounter <= 0 && thread->state == OSThreadState::Running) { if (!next) { // There is no thread to reschedule to return; } if (yield) { // Yield will transfer control to threads with equal or better priority if (thread->basePriority < next->thread->basePriority) { return; } } else { // Only reschedule to more important threads if (thread->basePriority <= next->thread->basePriority) { return; } } } // Change state to ready, only if this thread is running if (fiber->thread->state == OSThreadState::Running) { fiber->thread->state = OSThreadState::Ready; } // Add this fiber to queue queueNoLock(fiber); if (hasSchedulerLock) { OSUnlockScheduler(); } gLog->trace("Core {} leave thread {}", core->id, fiber->thread->id); // Return to main scheduler fiber lock.unlock(); SwitchToFiber(core->primaryFiber); // Reacquire scheduler lock if needed if (hasSchedulerLock) { OSLockScheduler(); } }
BOOL OSSetThreadAffinity(OSThread *thread, uint32_t affinity) { OSLockScheduler(); thread->attr &= ~OSThreadAttributes::AffinityAny; thread->attr |= affinity; OSRescheduleNoLock(); OSUnlockScheduler(); return TRUE; }
void SleepAlarmHandler(OSAlarm *alarm, OSContext *context) { OSLockScheduler(); // Wakeup the thread waiting on this alarm auto data = reinterpret_cast<SleepAlarmData*>(OSGetAlarmUserData(alarm)); OSWakeupOneThreadNoLock(data->thread); OSUnlockScheduler(); }
/** * Reset the event value to FALSE */ void OSResetEvent(OSEvent *event) { OSLockScheduler(); assert(event); assert(event->tag == OSEvent::Tag); // Reset event event->value = FALSE; OSUnlockScheduler(); }
BOOL OSSetThreadPriority(OSThread *thread, uint32_t priority) { if (priority > 31) { return FALSE; } OSLockScheduler(); thread->basePriority = priority; OSRescheduleNoLock(); OSUnlockScheduler(); return TRUE; }
int32_t OSResumeThread(OSThread *thread) { OSLockScheduler(); auto old = OSResumeThreadNoLock(thread, 1); if (thread->suspendCounter == 0) { OSRescheduleNoLock(); } OSUnlockScheduler(); return old; }
int32_t OSGetSemaphoreCount(OSSemaphore *semaphore) { int32_t count; OSLockScheduler(); assert(semaphore && semaphore->tag == OSSemaphore::Tag); // Return count count = semaphore->count; OSUnlockScheduler(); return count; }
BOOL OSRunThread(OSThread *thread, ThreadEntryPoint entry, uint32_t argc, p32<void> argv) { BOOL result = false; OSLockScheduler(); if (OSIsThreadTerminated(thread)) { InitialiseThreadState(thread, entry, argc, argv); OSResumeThreadNoLock(thread, 1); OSRescheduleNoLock(); } OSUnlockScheduler(); return result; }
int32_t OSWaitSemaphore(OSSemaphore *semaphore) { int32_t previous; OSLockScheduler(); assert(semaphore && semaphore->tag == OSSemaphore::Tag); while (semaphore->count <= 0) { // Wait until we can decrease semaphore OSSleepThreadNoLock(&semaphore->queue); OSRescheduleNoLock(); } previous = semaphore->count--; OSUnlockScheduler(); return previous; }
int32_t OSTryWaitSemaphore(OSSemaphore *semaphore) { int32_t previous; OSLockScheduler(); assert(semaphore && semaphore->tag == OSSemaphore::Tag); // Try to decrease semaphore previous = semaphore->count; if (semaphore->count > 0) { semaphore->count--; } OSUnlockScheduler(); return previous; }
BOOL OSSetThreadStackUsage(OSThread *thread) { OSLockScheduler(); if (!thread) { thread = OSGetCurrentThread(); } else if (thread->state == OSThreadState::Running) { OSUnlockScheduler(); return FALSE; } __OSClearThreadStack32(thread, 0xfefefefe); thread->attr |= OSThreadAttributes::StackUsage; OSUnlockScheduler(); return TRUE; }
int32_t OSSignalSemaphore(OSSemaphore *semaphore) { int32_t previous; OSLockScheduler(); assert(semaphore && semaphore->tag == OSSemaphore::Tag); // Increase semaphore previous = semaphore->count++; // Wakeup any waiting threads OSWakeupThreadNoLock(&semaphore->queue); OSRescheduleNoLock(); OSUnlockScheduler(); return previous; }
int32_t OSCheckThreadStackUsage(OSThread *thread) { uint32_t addr, result; OSLockScheduler(); for (addr = thread->stackEnd + 4; addr < thread->stackStart; addr += 4) { auto val = *reinterpret_cast<uint32_t*>(gMemory.translate(addr)); if (val != 0xfefefefe) { break; } } result = thread->stackStart - addr; OSUnlockScheduler(); return result; }
void OSExitThread(int value) { auto thread = OSGetCurrentThread(); OSLockScheduler(); thread->exitValue = value; if (thread->attr & OSThreadAttributes::Detached) { thread->state = OSThreadState::None; } else { thread->state = OSThreadState::Moribund; } OSWakeupThreadNoLock(&thread->joinQueue); OSWakeupThreadWaitForSuspensionNoLock(&thread->suspendQueue, -1); OSUnlockScheduler(); gProcessor.exit(); }
/** * Wait for an event value to be TRUE with a timeout * * Behaves the same than OSWaitEvent but with a timeout. * * Returns TRUE if the event was signalled, FALSE if wait timed out. */ BOOL OSWaitEventWithTimeout(OSEvent *event, OSTime timeout) { BOOL result = TRUE; OSLockScheduler(); // Check if event is already set if (event->value) { if (event->mode == OSEventMode::AutoReset) { // Reset event event->value = FALSE; } OSUnlockScheduler(); return TRUE; } // Setup some alarm data for callback auto data = OSAllocFromSystem<EventAlarmData>(); data->event = event; data->thread = OSGetCurrentThread(); data->timeout = FALSE; // Create an alarm to trigger timeout auto alarm = OSAllocFromSystem<OSAlarm>(); OSCreateAlarm(alarm); OSSetAlarmUserData(alarm, data); OSSetAlarm(alarm, timeout, pEventAlarmHandler); // Wait for the event OSSleepThreadNoLock(&event->queue); OSRescheduleNoLock(); if (data->timeout) { // Timed out, remove from wait queue OSEraseFromThreadQueue(&event->queue, data->thread); result = FALSE; } OSFreeToSystem(data); OSFreeToSystem(alarm); OSUnlockScheduler(); return result; }
BOOL OSWaitAlarm(OSAlarm *alarm) { OSAcquireSpinLock(gAlarmLock); assert(alarm); assert(alarm->tag == OSAlarm::Tag); if (alarm->state != OSAlarmState::Set) { OSReleaseSpinLock(gAlarmLock); return FALSE; } OSLockScheduler(); OSSleepThreadNoLock(&alarm->threadQueue); OSReleaseSpinLock(gAlarmLock); OSRescheduleNoLock(); OSUnlockScheduler(); return TRUE; }
uint32_t OSSuspendThread(OSThread *thread) { OSLockScheduler(); int32_t result; if (thread->state == OSThreadState::Moribund || thread->state == OSThreadState::None) { OSUnlockScheduler(); return -1; } if (thread->requestFlag == OSThreadRequest::Cancel) { OSUnlockScheduler(); return -1; } auto curThread = OSGetCurrentThread(); if (curThread == thread) { if (thread->cancelState) { OSUnlockScheduler(); return -1; } thread->needSuspend++; result = thread->suspendCounter; OSSuspendThreadNoLock(thread); OSRescheduleNoLock(); } else { if (thread->suspendCounter != 0) { result = thread->suspendCounter++; } else { thread->needSuspend++; thread->requestFlag = OSThreadRequest::Suspend; OSSleepThreadNoLock(&thread->suspendQueue); OSRescheduleNoLock(); result = thread->suspendResult; } } OSUnlockScheduler(); return result; }
BOOL OSJoinThread(OSThread *thread, be_val<int> *val) { OSLockScheduler(); if (thread->attr & OSThreadAttributes::Detached) { OSUnlockScheduler(); return FALSE; } if (thread->state != OSThreadState::Moribund) { OSSleepThreadNoLock(&thread->joinQueue); OSRescheduleNoLock(); } if (val) { *val = thread->exitValue; } OSUnlockScheduler(); return TRUE; }
BOOL OSTryLockMutex(OSMutex *mutex) { auto thread = OSGetCurrentThread(); OSLockScheduler(); OSTestThreadCancelNoLock(); if (mutex->owner && mutex->owner != thread) { // Someone else owns this mutex OSUnlockScheduler(); return FALSE; } if (mutex->owner != thread) { // Add to mutex queue OSAppendQueue(&thread->mutexQueue, mutex); } mutex->owner = thread; mutex->count++; OSUnlockScheduler(); return TRUE; }