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; }
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 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 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; }
/** * 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; }
void OSUnlockMutexNoLock(OSMutex *mutex) { auto thread = OSGetCurrentThread(); assert(mutex && mutex->tag == OSMutex::Tag); assert(mutex->owner == thread); assert(mutex->count > 0); mutex->count--; if (mutex->count == 0) { mutex->owner = nullptr; // Remove mutex from thread's mutex queue OSEraseFromQueue(&thread->mutexQueue, mutex); // Wakeup any threads trying to lock this mutex OSWakeupThreadNoLock(&mutex->queue); OSRescheduleNoLock(); } }
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; }
void OSLockMutexNoLock(OSMutex *mutex) { assert(mutex && mutex->tag == OSMutex::Tag); auto thread = OSGetCurrentThread(); while (mutex->owner && mutex->owner != thread) { thread->mutex = mutex; // Wait for other owner to unlock OSSleepThreadNoLock(&mutex->queue); OSRescheduleNoLock(); thread->mutex = nullptr; } if (mutex->owner != thread) { // Add to mutex queue OSAppendQueue(&thread->mutexQueue, mutex); } mutex->owner = thread; mutex->count++; }
void OSWaitCond(OSCondition *condition, OSMutex *mutex) { auto thread = OSGetCurrentThread(); OSLockScheduler(); assert(mutex && mutex->tag == OSMutex::Tag); assert(condition && condition->tag == OSCondition::Tag); assert(mutex->owner == thread); // Force an unlock auto mutexCount = mutex->count; mutex->count = 1; OSUnlockMutexNoLock(mutex); // Sleep on the condition OSSleepThreadNoLock(&condition->queue); OSRescheduleNoLock(); // Restore lock OSLockMutexNoLock(mutex); mutex->count = mutexCount; OSUnlockScheduler(); }
void OSSleepTicks(OSTime ticks) { 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(); }