]>
git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOConditionLock.cpp
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
26 * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
28 * AppleIOPSSafeCondLock.m. Lock object with exported condition variable,
33 * 01-Aug-91 Doug Mitchell at NeXT
37 #include <IOKit/IOConditionLock.h>
39 #define super OSObject
40 OSDefineMetaClassAndStructors(IOConditionLock
, OSObject
)
42 bool IOConditionLock::initWithCondition(int inCondition
, bool inIntr
= true)
47 cond_interlock
= IOLockAlloc();
48 sleep_interlock
= IOLockAlloc();
50 condition
= inCondition
;
53 interruptible
= (inIntr
) ? THREAD_INTERRUPTIBLE
: THREAD_UNINT
;
55 return cond_interlock
&& sleep_interlock
;
58 IOConditionLock
*IOConditionLock::withCondition(int condition
, bool intr
= true)
60 IOConditionLock
*me
= new IOConditionLock
;
62 if (me
&& !me
->initWithCondition(condition
, intr
)) {
69 void IOConditionLock::free()
72 IOLockFree(cond_interlock
);
74 IOLockFree(sleep_interlock
);
78 bool IOConditionLock::getInterruptible() const
83 int IOConditionLock:: getCondition() const
88 int IOConditionLock:: setCondition(int inCondition
)
92 condition
= inCondition
;
93 thread_wakeup_one((void *) &condition
);
98 void IOConditionLock::unlock()
100 IOTakeLock(sleep_interlock
);
102 thread_wakeup_one((void *) &condition
);
107 IOLockWakeup(sleep_interlock
, this, /* one-thread */ false); // Wakeup everybody
110 IOUnlock(sleep_interlock
);
113 void IOConditionLock::unlockWith(int inCondition
)
115 IOTakeLock(sleep_interlock
);
116 IOTakeLock(cond_interlock
);
118 condition
= inCondition
;
120 IOUnlock(cond_interlock
);
121 IOUnlock(sleep_interlock
);
126 bool IOConditionLock::tryLock()
130 IOTakeLock(sleep_interlock
);
136 IOUnlock(sleep_interlock
);
141 int IOConditionLock::lock()
143 int thread_res
= THREAD_AWAKENED
;
145 IOTakeLock(sleep_interlock
);
147 /* Try to acquire the want_lock bit. */
148 while (want_lock
&& thread_res
== THREAD_AWAKENED
)
151 thread_res
= IOLockSleep(sleep_interlock
, (void *) this, interruptible
);
153 if (thread_res
== THREAD_AWAKENED
)
156 IOUnlock(sleep_interlock
);
161 int IOConditionLock::lockWhen(int inCondition
)
167 /* First get the actual lock */
169 if (thread_res
!= THREAD_AWAKENED
)
170 break; // Failed to acquire lock
172 if (inCondition
== condition
)
173 break; // Hold lock and condition is expected value
176 * Need to hold a IOTakeLock when we call thread_sleep().
177 * Both _cond_interlock and want_lock must be held to
180 IOTakeLock(cond_interlock
);
181 unlock(); // Release lock and sleep
184 * this is the critical section on a multi in which
185 * another thread could hold _sleep_interlock, but they
186 * can't change _condition. Holding _cond_interlock here
187 * (until after assert_wait() is called from
188 * thread_sleep()) ensures that we'll be notified
189 * of changes in _condition.
191 assert_wait((void *) &condition
, interruptible
); /* assert event */
192 IOUnlock(cond_interlock
); /* release the lock */
193 thread_res
= thread_block(THREAD_CONTINUE_NULL
); /* block ourselves */
194 } while (thread_res
== THREAD_AWAKENED
);