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 NULL;
}
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;
}