Example #1
0
/**
 * Sleep the current thread until the condition variable has been signalled.
 *
 * The mutex must be locked when entering this function.
 * Will unlock the mutex and then sleep, reacquiring the mutex when woken.
 *
 * Similar to <a href="http://en.cppreference.com/w/cpp/thread/condition_variable/wait">std::condition_variable::wait</a>.
 */
void
OSWaitCond(OSCondition *condition, OSMutex *mutex)
{
   auto thread = OSGetCurrentThread();
   internal::lockScheduler();
   decaf_check(mutex && mutex->tag == OSMutex::Tag);
   decaf_check(condition && condition->tag == OSCondition::Tag);
   decaf_check(mutex->owner == thread);

   // Force an unlock
   auto mutexCount = mutex->count;
   mutex->count = 1;
   unlockMutexNoLock(mutex);
   internal::rescheduleOtherCoreNoLock();

   // Sleep on the condition
   internal::sleepThreadNoLock(&condition->queue);
   internal::rescheduleSelfNoLock();

   // Restore lock
   lockMutexNoLock(mutex);
   mutex->count = mutexCount;

   internal::unlockScheduler();
}
Example #2
0
/**
 * Lock the mutex.
 *
 * If no one owns the mutex, set current thread as owner.
 * If the lock is owned by the current thread, increase the recursion count.
 * If the lock is owned by another thread, the current thread will sleep until
 * the owner has unlocked this mutex.
 *
 * Similar to <a href="http://en.cppreference.com/w/cpp/thread/recursive_mutex/lock">std::recursive_mutex::lock</a>.
 */
void
OSLockMutex(virt_ptr<OSMutex> mutex)
{
   internal::lockScheduler();
   internal::testThreadCancelNoLock();
   lockMutexNoLock(mutex);
   internal::unlockScheduler();
}
Example #3
0
/**
 * Sleep the current thread until the condition variable has been signalled.
 *
 * The mutex must be locked when entering this function.
 * Will unlock the mutex and then sleep, reacquiring the mutex when woken.
 *
 * Similar to <a href="http://en.cppreference.com/w/cpp/thread/condition_variable/wait">std::condition_variable::wait</a>.
 */
void
OSWaitCond(virt_ptr<OSCondition> condition,
           virt_ptr<OSMutex> mutex)
{
   internal::lockScheduler();
   auto thread = OSGetCurrentThread();
   decaf_check(thread->state == OSThreadState::Running);
   decaf_check(mutex->owner == thread);

   // Save the count and then unlock the mutex
   auto mutexCount = mutex->count;
   mutex->count = 0;
   mutex->owner = nullptr;

   // Remove mutex from thread's mutex queue
   MutexQueue::erase(virt_addrof(thread->mutexQueue), mutex);

   // If we have a promoted priority, reset it.
   if (thread->priority < thread->basePriority) {
      thread->priority = internal::calculateThreadPriorityNoLock(thread);
   }

   // Wake anyone waiting on the mutex
   internal::disableScheduler();
   internal::wakeupThreadNoLock(virt_addrof(mutex->queue));
   internal::rescheduleAllCoreNoLock();
   internal::enableScheduler();

   // Sleep on the condition
   internal::sleepThreadNoLock(virt_addrof(condition->queue));
   internal::rescheduleSelfNoLock();

   // Relock the mutex
   lockMutexNoLock(mutex);
   mutex->count = mutexCount;

   internal::unlockScheduler();
}