]>
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_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
29 * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
31 * AppleIOPSSafeCondLock.m. Lock object with exported condition variable,
36 * 01-Aug-91 Doug Mitchell at NeXT
40 #include <IOKit/IOConditionLock.h>
42 #define super OSObject
43 OSDefineMetaClassAndStructors(IOConditionLock
, OSObject
)
45 bool IOConditionLock::initWithCondition(int inCondition
, bool inIntr
)
50 cond_interlock
= IOLockAlloc();
51 sleep_interlock
= IOLockAlloc();
53 condition
= inCondition
;
56 interruptible
= (inIntr
) ? THREAD_INTERRUPTIBLE
: THREAD_UNINT
;
58 return cond_interlock
&& sleep_interlock
;
61 IOConditionLock
*IOConditionLock::withCondition(int condition
, bool intr
)
63 IOConditionLock
*me
= new IOConditionLock
;
65 if (me
&& !me
->initWithCondition(condition
, intr
)) {
72 void IOConditionLock::free()
75 IOLockFree(cond_interlock
);
77 IOLockFree(sleep_interlock
);
81 bool IOConditionLock::getInterruptible() const
86 int IOConditionLock:: getCondition() const
91 int IOConditionLock:: setCondition(int inCondition
)
95 condition
= inCondition
;
96 thread_wakeup_one((void *) &condition
);
101 void IOConditionLock::unlock()
103 IOTakeLock(sleep_interlock
);
105 thread_wakeup_one((void *) &condition
);
110 IOLockWakeup(sleep_interlock
, this, /* one-thread */ false); // Wakeup everybody
113 IOUnlock(sleep_interlock
);
116 void IOConditionLock::unlockWith(int inCondition
)
118 IOTakeLock(sleep_interlock
);
119 IOTakeLock(cond_interlock
);
121 condition
= inCondition
;
123 IOUnlock(cond_interlock
);
124 IOUnlock(sleep_interlock
);
129 bool IOConditionLock::tryLock()
133 IOTakeLock(sleep_interlock
);
139 IOUnlock(sleep_interlock
);
144 int IOConditionLock::lock()
146 int thread_res
= THREAD_AWAKENED
;
148 IOTakeLock(sleep_interlock
);
150 /* Try to acquire the want_lock bit. */
151 while (want_lock
&& thread_res
== THREAD_AWAKENED
)
154 thread_res
= IOLockSleep(sleep_interlock
, (void *) this, interruptible
);
156 if (thread_res
== THREAD_AWAKENED
)
159 IOUnlock(sleep_interlock
);
164 int IOConditionLock::lockWhen(int inCondition
)
170 /* First get the actual lock */
172 if (thread_res
!= THREAD_AWAKENED
)
173 break; // Failed to acquire lock
175 if (inCondition
== condition
)
176 break; // Hold lock and condition is expected value
179 * Need to hold a IOTakeLock when we call thread_sleep().
180 * Both _cond_interlock and want_lock must be held to
183 IOTakeLock(cond_interlock
);
184 unlock(); // Release lock and sleep
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.
194 assert_wait((void *) &condition
, interruptible
); /* assert event */
195 IOUnlock(cond_interlock
); /* release the lock */
196 thread_res
= thread_block(THREAD_CONTINUE_NULL
); /* block ourselves */
197 } while (thread_res
== THREAD_AWAKENED
);