IOConditionLock.cpp [plain text]
#include <IOKit/IOConditionLock.h>
#define super OSObject
OSDefineMetaClassAndStructors(IOConditionLock, OSObject)
bool IOConditionLock::initWithCondition(int inCondition, bool inIntr)
{
if (!super::init())
return false;
cond_interlock = IOLockAlloc();
sleep_interlock = IOLockAlloc();
condition = inCondition;
want_lock = false;
waiting = false;
interruptible = (inIntr) ? THREAD_INTERRUPTIBLE : THREAD_UNINT;
return cond_interlock && sleep_interlock;
}
IOConditionLock *IOConditionLock::withCondition(int condition, bool intr)
{
IOConditionLock *me = new IOConditionLock;
if (me && !me->initWithCondition(condition, intr)) {
me->release();
return 0;
}
return me;
}
void IOConditionLock::free()
{
if (cond_interlock)
IOLockFree(cond_interlock);
if (sleep_interlock)
IOLockFree(sleep_interlock);
super::free();
}
bool IOConditionLock::getInterruptible() const
{
return interruptible;
}
int IOConditionLock:: getCondition() const
{
return condition;
}
int IOConditionLock:: setCondition(int inCondition)
{
int old = condition;
condition = inCondition;
thread_wakeup_one((void *) &condition);
return old;
}
void IOConditionLock::unlock()
{
IOTakeLock(sleep_interlock);
thread_wakeup_one((void *) &condition);
want_lock = false;
if (waiting) {
waiting = false;
IOLockWakeup(sleep_interlock, this, false); }
IOUnlock(sleep_interlock);
}
void IOConditionLock::unlockWith(int inCondition)
{
IOTakeLock(sleep_interlock);
IOTakeLock(cond_interlock);
condition = inCondition;
IOUnlock(cond_interlock);
IOUnlock(sleep_interlock);
unlock();
}
bool IOConditionLock::tryLock()
{
bool result;
IOTakeLock(sleep_interlock);
result = !want_lock;
if (result)
want_lock = true;
IOUnlock(sleep_interlock);
return result;
}
int IOConditionLock::lock()
{
int thread_res = THREAD_AWAKENED;
IOTakeLock(sleep_interlock);
while (want_lock && thread_res == THREAD_AWAKENED)
{
waiting = true;
thread_res = IOLockSleep(sleep_interlock, (void *) this, interruptible);
}
if (thread_res == THREAD_AWAKENED)
want_lock = true;
IOUnlock(sleep_interlock);
return thread_res;
}
int IOConditionLock::lockWhen(int inCondition)
{
int thread_res;
do
{
thread_res = lock();
if (thread_res != THREAD_AWAKENED)
break;
if (inCondition == condition)
break;
IOTakeLock(cond_interlock);
unlock();
assert_wait((void *) &condition, interruptible);
IOUnlock(cond_interlock);
thread_res = thread_block(THREAD_CONTINUE_NULL);
} while (thread_res == THREAD_AWAKENED);
return thread_res;
}