/**
 * Set a repeated alarm to execute a callback every interval from start.
 */
BOOL
OSSetPeriodicAlarm(OSAlarm *alarm, OSTime start, OSTime interval, AlarmCallback callback)
{
    ScopedSpinLock lock(gAlarmLock);

    // Set alarm
    alarm->nextFire = start;
    alarm->callback = callback;
    alarm->period = interval;
    alarm->context = nullptr;
    alarm->state = OSAlarmState::Set;

    // Erase from old alarm queue
    if (alarm->alarmQueue) {
        OSEraseFromQueue(static_cast<OSAlarmQueue*>(alarm->alarmQueue), alarm);
        alarm->alarmQueue = nullptr;
    }

    // Add to this core's alarm queue
    auto core = OSGetCoreId();
    auto queue = gAlarmQueue[core];
    alarm->alarmQueue = queue;
    OSAppendQueue(queue, alarm);

    // Set the interrupt timer in processor
    gProcessor.setInterruptTimer(core, coreinit::internal::toTimepoint(alarm->nextFire));
    return TRUE;
}
static BOOL
OSCancelAlarmNoLock(OSAlarm *alarm)
{
   if (!alarm->state == OSAlarmState::Set) {
      return FALSE;
   }

   alarm->state = OSAlarmState::Cancelled;
   alarm->nextFire = 0;
   alarm->period = 0;
   OSEraseFromQueue(static_cast<OSAlarmQueue*>(alarm->alarmQueue), alarm);
   return TRUE;
}
Exemple #3
0
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();
   }
}
static bool
OSTriggerAlarmNoLock(OSAlarm *alarm, OSContext *context)
{
   alarm->context = context;

   if (alarm->callback && alarm->state != OSAlarmState::Cancelled) {
      alarm->callback(alarm, context);
   }

   OSWakeupThread(&alarm->threadQueue);

   if (alarm->period) {
      alarm->nextFire = OSGetTime() + alarm->period;
      alarm->state = OSAlarmState::Set;
   } else {
      alarm->nextFire = 0;
      alarm->state = OSAlarmState::None;
      OSEraseFromQueue(static_cast<OSAlarmQueue*>(alarm->alarmQueue), alarm);
   }

   return alarm->nextFire == 0;
}
void
OSEraseFromThreadQueue(OSThreadQueue *queue, OSThread *thread)
{
   OSEraseFromQueue(queue, thread);
}