|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1997 Apple Computer, Inc. All rights reserved. ! 23: * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved. ! 24: * ! 25: * AppleIOPSSafeCondLock.m. Lock object with exported condition variable, ! 26: * kernel version. ! 27: * ! 28: * HISTORY ! 29: * 1997-11- ! 30: * 01-Aug-91 Doug Mitchell at NeXT ! 31: * Created. ! 32: */ ! 33: ! 34: #include <IOKit/IOConditionLock.h> ! 35: ! 36: #define super OSObject ! 37: OSDefineMetaClassAndStructors(IOConditionLock, OSObject) ! 38: ! 39: bool IOConditionLock::initWithCondition(int inCondition, bool inIntr = true) ! 40: { ! 41: if (!super::init()) ! 42: return false; ! 43: ! 44: cond_interlock = IOLockAlloc(); ! 45: sleep_interlock = IOLockAlloc(); ! 46: ! 47: condition = inCondition; ! 48: want_lock = false; ! 49: waiting = false; ! 50: interruptible = (inIntr) ? THREAD_INTERRUPTIBLE : THREAD_UNINT; ! 51: ! 52: return cond_interlock && sleep_interlock; ! 53: } ! 54: ! 55: IOConditionLock *IOConditionLock::withCondition(int condition, bool intr = true) ! 56: { ! 57: IOConditionLock *me = new IOConditionLock; ! 58: ! 59: if (me && !me->initWithCondition(condition, intr)) { ! 60: me->free(); ! 61: return 0; ! 62: } ! 63: ! 64: return me; ! 65: } ! 66: void IOConditionLock::free() ! 67: { ! 68: if (cond_interlock) ! 69: IOLockFree(cond_interlock); ! 70: if (sleep_interlock) ! 71: IOLockFree(sleep_interlock); ! 72: super::free(); ! 73: } ! 74: ! 75: bool IOConditionLock::getInterruptible() const ! 76: { ! 77: return interruptible; ! 78: } ! 79: ! 80: int IOConditionLock:: getCondition() const ! 81: { ! 82: return condition; ! 83: } ! 84: ! 85: int IOConditionLock:: setCondition(int inCondition) ! 86: { ! 87: int old = condition; ! 88: ! 89: condition = inCondition; ! 90: thread_wakeup_one((void *) &condition); ! 91: ! 92: return old; ! 93: } ! 94: ! 95: void IOConditionLock::unlock() ! 96: { ! 97: IOTakeLock(sleep_interlock); ! 98: ! 99: thread_wakeup_one((void *) &condition); ! 100: ! 101: want_lock = false; ! 102: if (waiting) { ! 103: waiting = false; ! 104: thread_wakeup(this); // Wakeup everybody ! 105: } ! 106: ! 107: IOUnlock(sleep_interlock); ! 108: } ! 109: ! 110: void IOConditionLock::unlockWith(int inCondition) ! 111: { ! 112: IOTakeLock(sleep_interlock); ! 113: IOTakeLock(cond_interlock); ! 114: ! 115: condition = inCondition; ! 116: ! 117: IOUnlock(cond_interlock); ! 118: IOUnlock(sleep_interlock); ! 119: ! 120: unlock(); ! 121: } ! 122: ! 123: bool IOConditionLock::tryLock() ! 124: { ! 125: bool result; ! 126: ! 127: IOTakeLock(sleep_interlock); ! 128: ! 129: result = !want_lock; ! 130: if (result) ! 131: want_lock = true; ! 132: ! 133: IOUnlock(sleep_interlock); ! 134: ! 135: return result; ! 136: } ! 137: ! 138: int IOConditionLock::lock() ! 139: { ! 140: int thread_res = THREAD_AWAKENED; ! 141: ! 142: IOTakeLock(sleep_interlock); ! 143: ! 144: /* Try to acquire the want_lock bit. */ ! 145: while (want_lock && thread_res == THREAD_AWAKENED) ! 146: { ! 147: waiting = true; ! 148: ! 149: assert_wait((void *) this, interruptible); /* assert event */ ! 150: IOUnlock(sleep_interlock); /* release the lock */ ! 151: thread_block((void (*)(void)) 0); /* block ourselves */ ! 152: ! 153: IOTakeLock(sleep_interlock); ! 154: thread_res = thread_wait_result(); ! 155: } ! 156: if (thread_res == THREAD_AWAKENED) ! 157: want_lock = true; ! 158: ! 159: IOUnlock(sleep_interlock); ! 160: ! 161: return thread_res; ! 162: } ! 163: ! 164: int IOConditionLock::lockWhen(int inCondition) ! 165: { ! 166: int thread_res; ! 167: ! 168: do ! 169: { ! 170: /* First get the actual lock */ ! 171: thread_res = lock(); ! 172: if (thread_res != THREAD_AWAKENED) ! 173: break; // Failed to acquire lock ! 174: ! 175: if (inCondition == condition) ! 176: break; // Hold lock and condition is expected value ! 177: ! 178: /* ! 179: * Need to hold a IOTakeLock when we call thread_sleep(). ! 180: * Both _cond_interlock and want_lock must be held to ! 181: * change _condition. ! 182: */ ! 183: IOTakeLock(cond_interlock); ! 184: unlock(); // Release lock and sleep ! 185: ! 186: /* ! 187: * this is the critical section on a multi in which ! 188: * another thread could hold _sleep_interlock, but they ! 189: * can't change _condition. Holding _cond_interlock here ! 190: * (until after assert_wait() is called from ! 191: * thread_sleep()) ensures that we'll be notified ! 192: * of changes in _condition. ! 193: */ ! 194: assert_wait((void *) &condition, interruptible); /* assert event */ ! 195: IOUnlock(cond_interlock); /* release the lock */ ! 196: thread_block((void (*)(void)) 0); /* block ourselves */ ! 197: ! 198: thread_res = thread_wait_result(); ! 199: } while (thread_res == THREAD_AWAKENED); ! 200: ! 201: return thread_res; ! 202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.