/**
 * 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;
}
Exemple #2
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;
}
Exemple #3
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++;
}