/** * 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; }
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; }
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++; }