|
|
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.