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();
}
Exemple #4
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();
}
void
OSWakeupThread(OSThreadQueue *queue)
{
   OSLockScheduler();
   OSWakeupThreadNoLock(queue);
   OSUnlockScheduler();
}
Exemple #6
0
/**
 * 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();
}
Exemple #8
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();
}
void
OSContinueThread(OSThread *thread)
{
   OSLockScheduler();
   OSResumeThreadNoLock(thread, thread->suspendCounter);
   OSRescheduleNoLock();
   OSUnlockScheduler();
}
Exemple #10
0
void
OSSleepThread(OSThreadQueue *queue)
{
   OSLockScheduler();
   OSSleepThreadNoLock(queue);
   OSRescheduleNoLock();
   OSUnlockScheduler();
}
Exemple #11
0
void
OSUnlockMutex(OSMutex *mutex)
{
   OSLockScheduler();
   OSUnlockMutexNoLock(mutex);
   OSTestThreadCancelNoLock();
   OSUnlockScheduler();
}
Exemple #12
0
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();
    }
}
Exemple #13
0
BOOL
OSSetThreadAffinity(OSThread *thread, uint32_t affinity)
{
   OSLockScheduler();
   thread->attr &= ~OSThreadAttributes::AffinityAny;
   thread->attr |= affinity;
   OSRescheduleNoLock();
   OSUnlockScheduler();
   return TRUE;
}
Exemple #14
0
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();
}
Exemple #15
0
/**
 * Reset the event value to FALSE
 */
void
OSResetEvent(OSEvent *event)
{
   OSLockScheduler();
   assert(event);
   assert(event->tag == OSEvent::Tag);

   // Reset event
   event->value = FALSE;

   OSUnlockScheduler();
}
Exemple #16
0
BOOL
OSSetThreadPriority(OSThread *thread, uint32_t priority)
{
   if (priority > 31) {
      return FALSE;
   }

   OSLockScheduler();
   thread->basePriority = priority;
   OSRescheduleNoLock();
   OSUnlockScheduler();
   return TRUE;
}
Exemple #17
0
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;
}
Exemple #19
0
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;
}
Exemple #22
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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();
}
Exemple #26
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;
}
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;
}
Exemple #28
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;
}
Exemple #29
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;
}
Exemple #30
0
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;
}