]>
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 * 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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
23 * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
25 * AppleIOPSSafeCondLock.m. Lock object with exported condition variable,
30 * 01-Aug-91 Doug Mitchell at NeXT
34 #include <IOKit/IOConditionLock.h>
36 #define super OSObject
37 OSDefineMetaClassAndStructors(IOConditionLock
, OSObject
)
39 bool IOConditionLock::initWithCondition(int inCondition
, bool inIntr
= true)
44 cond_interlock
= IOLockAlloc();
45 sleep_interlock
= IOLockAlloc();
47 condition
= inCondition
;
50 interruptible
= (inIntr
) ? THREAD_INTERRUPTIBLE
: THREAD_UNINT
;
52 return cond_interlock
&& sleep_interlock
;
55 IOConditionLock
*IOConditionLock::withCondition(int condition
, bool intr
= true)
57 IOConditionLock
*me
= new IOConditionLock
;
59 if (me
&& !me
->initWithCondition(condition
, intr
)) {
66 void IOConditionLock::free()
69 IOLockFree(cond_interlock
);
71 IOLockFree(sleep_interlock
);
75 bool IOConditionLock::getInterruptible() const
80 int IOConditionLock:: getCondition() const
85 int IOConditionLock:: setCondition(int inCondition
)
89 condition
= inCondition
;
90 thread_wakeup_one((void *) &condition
);
95 void IOConditionLock::unlock()
97 IOTakeLock(sleep_interlock
);
99 thread_wakeup_one((void *) &condition
);
104 thread_wakeup(this); // Wakeup everybody
107 IOUnlock(sleep_interlock
);
110 void IOConditionLock::unlockWith(int inCondition
)
112 IOTakeLock(sleep_interlock
);
113 IOTakeLock(cond_interlock
);
115 condition
= inCondition
;
117 IOUnlock(cond_interlock
);
118 IOUnlock(sleep_interlock
);
123 bool IOConditionLock::tryLock()
127 IOTakeLock(sleep_interlock
);
133 IOUnlock(sleep_interlock
);
138 int IOConditionLock::lock()
140 int thread_res
= THREAD_AWAKENED
;
142 IOTakeLock(sleep_interlock
);
144 /* Try to acquire the want_lock bit. */
145 while (want_lock
&& thread_res
== THREAD_AWAKENED
)
149 assert_wait((void *) this, interruptible
); /* assert event */
150 IOUnlock(sleep_interlock
); /* release the lock */
151 thread_res
= thread_block((void (*)(void)) 0); /* block ourselves */
153 IOTakeLock(sleep_interlock
);
155 if (thread_res
== THREAD_AWAKENED
)
158 IOUnlock(sleep_interlock
);
163 int IOConditionLock::lockWhen(int inCondition
)
169 /* First get the actual lock */
171 if (thread_res
!= THREAD_AWAKENED
)
172 break; // Failed to acquire lock
174 if (inCondition
== condition
)
175 break; // Hold lock and condition is expected value
178 * Need to hold a IOTakeLock when we call thread_sleep().
179 * Both _cond_interlock and want_lock must be held to
182 IOTakeLock(cond_interlock
);
183 unlock(); // Release lock and sleep
186 * this is the critical section on a multi in which
187 * another thread could hold _sleep_interlock, but they
188 * can't change _condition. Holding _cond_interlock here
189 * (until after assert_wait() is called from
190 * thread_sleep()) ensures that we'll be notified
191 * of changes in _condition.
193 assert_wait((void *) &condition
, interruptible
); /* assert event */
194 IOUnlock(cond_interlock
); /* release the lock */
195 thread_res
= thread_block((void (*)(void)) 0); /* block ourselves */
196 } while (thread_res
== THREAD_AWAKENED
);