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(); }
/** * 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 OSSleepThread(OSThreadQueue *queue) { OSLockScheduler(); OSSleepThreadNoLock(queue); OSRescheduleNoLock(); OSUnlockScheduler(); }
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; }
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 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; }
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(); }