Beispiel #1
0
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();
}
Beispiel #2
0
/**
 * 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();
}
Beispiel #3
0
void
OSSleepThread(OSThreadQueue *queue)
{
   OSLockScheduler();
   OSSleepThreadNoLock(queue);
   OSRescheduleNoLock();
   OSUnlockScheduler();
}
Beispiel #4
0
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;
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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++;
}
Beispiel #10
0
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();
}
Beispiel #11
0
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();
}