]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOLocks.cpp
xnu-6153.81.5.tar.gz
[apple/xnu.git] / iokit / Kernel / IOLocks.cpp
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 1998-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
91447636 28
1c79356b
A
29#include <IOKit/system.h>
30
31#include <IOKit/IOReturn.h>
0a7de745 32#include <IOKit/IOLib.h>
1c79356b
A
33#include <IOKit/assert.h>
34
2d21ac55
A
35#include <IOKit/IOLocksPrivate.h>
36
1c79356b 37extern "C" {
91447636
A
38#include <kern/locks.h>
39
fe8ab488
A
40#if defined(__x86_64__)
41/* Synthetic event if none is specified, for backwards compatibility only. */
42static bool IOLockSleep_NO_EVENT __attribute__((used)) = 0;
43#endif
44
0a7de745
A
45void
46IOLockInitWithState( IOLock * lock, IOLockState state)
91447636 47{
0a7de745
A
48 if (state == kIOLockStateLocked) {
49 lck_mtx_lock( lock);
50 }
91447636 51}
1c79356b 52
0a7de745
A
53IOLock *
54IOLockAlloc( void )
1c79356b 55{
0a7de745 56 return lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
1c79356b
A
57}
58
0a7de745
A
59void
60IOLockFree( IOLock * lock)
1c79356b 61{
0a7de745 62 lck_mtx_free( lock, IOLockGroup);
1c79356b
A
63}
64
0a7de745
A
65lck_mtx_t *
66IOLockGetMachLock( IOLock * lock)
1c79356b 67{
0a7de745 68 return (lck_mtx_t *)lock;
1c79356b
A
69}
70
0a7de745
A
71int
72IOLockSleep( IOLock * lock, void *event, UInt32 interType)
91447636 73{
0a7de745 74 return (int) lck_mtx_sleep(lock, LCK_SLEEP_PROMOTED_PRI, (event_t) event, (wait_interrupt_t) interType);
91447636
A
75}
76
0a7de745
A
77int
78IOLockSleepDeadline( IOLock * lock, void *event,
79 AbsoluteTime deadline, UInt32 interType)
91447636 80{
0a7de745
A
81 return (int) lck_mtx_sleep_deadline(lock, LCK_SLEEP_PROMOTED_PRI, (event_t) event,
82 (wait_interrupt_t) interType, __OSAbsoluteTime(deadline));
91447636
A
83}
84
0a7de745
A
85void
86IOLockWakeup(IOLock * lock, void *event, bool oneThread)
87{
91447636 88 thread_wakeup_prim((event_t) event, oneThread, THREAD_AWAKENED);
0a7de745 89}
91447636 90
5c9f4661 91
fe8ab488
A
92#if defined(__x86_64__)
93/*
94 * For backwards compatibility, kexts built against pre-Darwin 14 headers will bind at runtime to this function,
95 * which supports a NULL event,
96 */
0a7de745
A
97int IOLockSleep_legacy_x86_64( IOLock * lock, void *event, UInt32 interType) __asm("_IOLockSleep");
98int IOLockSleepDeadline_legacy_x86_64( IOLock * lock, void *event,
99 AbsoluteTime deadline, UInt32 interType) __asm("_IOLockSleepDeadline");
100void IOLockWakeup_legacy_x86_64(IOLock * lock, void *event, bool oneThread) __asm("_IOLockWakeup");
fe8ab488 101
0a7de745
A
102int
103IOLockSleep_legacy_x86_64( IOLock * lock, void *event, UInt32 interType)
fe8ab488 104{
0a7de745
A
105 if (event == NULL) {
106 event = (void *)&IOLockSleep_NO_EVENT;
107 }
fe8ab488 108
0a7de745 109 return IOLockSleep(lock, event, interType);
fe8ab488
A
110}
111
0a7de745
A
112int
113IOLockSleepDeadline_legacy_x86_64( IOLock * lock, void *event,
114 AbsoluteTime deadline, UInt32 interType)
fe8ab488 115{
0a7de745
A
116 if (event == NULL) {
117 event = (void *)&IOLockSleep_NO_EVENT;
118 }
fe8ab488 119
0a7de745 120 return IOLockSleepDeadline(lock, event, deadline, interType);
fe8ab488
A
121}
122
0a7de745
A
123void
124IOLockWakeup_legacy_x86_64(IOLock * lock, void *event, bool oneThread)
125{
126 if (event == NULL) {
127 event = (void *)&IOLockSleep_NO_EVENT;
128 }
fe8ab488 129
0a7de745
A
130 IOLockWakeup(lock, event, oneThread);
131}
fe8ab488
A
132#endif /* defined(__x86_64__) */
133
91447636 134
1c79356b 135struct _IORecursiveLock {
0a7de745
A
136 lck_mtx_t mutex;
137 lck_grp_t *group;
138 thread_t thread;
139 UInt32 count;
1c79356b
A
140};
141
0a7de745
A
142IORecursiveLock *
143IORecursiveLockAllocWithLockGroup( lck_grp_t * lockGroup )
1c79356b 144{
0a7de745 145 _IORecursiveLock * lock;
1c79356b 146
cb323159
A
147 if (lockGroup == NULL) {
148 return NULL;
0a7de745 149 }
1c79356b 150
0a7de745
A
151 lock = IONew( _IORecursiveLock, 1 );
152 if (!lock) {
cb323159 153 return NULL;
0a7de745 154 }
2d21ac55 155
0a7de745
A
156 lck_mtx_init( &lock->mutex, lockGroup, LCK_ATTR_NULL );
157 lock->group = lockGroup;
cb323159 158 lock->thread = NULL;
0a7de745 159 lock->count = 0;
1c79356b 160
0a7de745 161 return (IORecursiveLock *) lock;
1c79356b
A
162}
163
2d21ac55 164
0a7de745
A
165IORecursiveLock *
166IORecursiveLockAlloc( void )
2d21ac55 167{
0a7de745 168 return IORecursiveLockAllocWithLockGroup( IOLockGroup );
2d21ac55
A
169}
170
0a7de745
A
171void
172IORecursiveLockFree( IORecursiveLock * _lock )
1c79356b 173{
0a7de745
A
174 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
175
176 lck_mtx_destroy(&lock->mutex, lock->group);
177 IODelete( lock, _IORecursiveLock, 1 );
1c79356b
A
178}
179
0a7de745
A
180lck_mtx_t *
181IORecursiveLockGetMachLock( IORecursiveLock * lock )
91447636 182{
0a7de745 183 return &lock->mutex;
91447636
A
184}
185
0a7de745
A
186void
187IORecursiveLockLock( IORecursiveLock * _lock)
1c79356b 188{
0a7de745
A
189 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
190
191 if (lock->thread == IOThreadSelf()) {
192 lock->count++;
193 } else {
194 lck_mtx_lock( &lock->mutex );
cb323159 195 assert( lock->thread == NULL );
0a7de745
A
196 assert( lock->count == 0 );
197 lock->thread = IOThreadSelf();
198 lock->count = 1;
199 }
1c79356b
A
200}
201
0a7de745
A
202boolean_t
203IORecursiveLockTryLock( IORecursiveLock * _lock)
1c79356b 204{
0a7de745
A
205 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
206
207 if (lock->thread == IOThreadSelf()) {
208 lock->count++;
209 return true;
210 } else {
211 if (lck_mtx_try_lock( &lock->mutex )) {
cb323159 212 assert( lock->thread == NULL );
0a7de745
A
213 assert( lock->count == 0 );
214 lock->thread = IOThreadSelf();
215 lock->count = 1;
216 return true;
217 }
1c79356b 218 }
0a7de745 219 return false;
1c79356b
A
220}
221
0a7de745
A
222void
223IORecursiveLockUnlock( IORecursiveLock * _lock)
1c79356b 224{
0a7de745 225 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
1c79356b 226
0a7de745 227 assert( lock->thread == IOThreadSelf());
1c79356b 228
0a7de745 229 if (0 == (--lock->count)) {
cb323159 230 lock->thread = NULL;
0a7de745
A
231 lck_mtx_unlock( &lock->mutex );
232 }
1c79356b
A
233}
234
0a7de745
A
235boolean_t
236IORecursiveLockHaveLock( const IORecursiveLock * _lock)
1c79356b 237{
0a7de745 238 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
1c79356b 239
0a7de745 240 return lock->thread == IOThreadSelf();
1c79356b
A
241}
242
0a7de745
A
243int
244IORecursiveLockSleep(IORecursiveLock *_lock, void *event, UInt32 interType)
1c79356b 245{
0a7de745
A
246 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
247 UInt32 count = lock->count;
248 int res;
249
250 assert(lock->thread == IOThreadSelf());
251
252 lock->count = 0;
cb323159 253 lock->thread = NULL;
0a7de745
A
254 res = lck_mtx_sleep(&lock->mutex, LCK_SLEEP_PROMOTED_PRI, (event_t) event, (wait_interrupt_t) interType);
255
256 // Must re-establish the recursive lock no matter why we woke up
257 // otherwise we would potentially leave the return path corrupted.
cb323159 258 assert(lock->thread == NULL);
0a7de745
A
259 assert(lock->count == 0);
260 lock->thread = IOThreadSelf();
261 lock->count = count;
262 return res;
b0d623f7
A
263}
264
0a7de745
A
265int
266IORecursiveLockSleepDeadline( IORecursiveLock * _lock, void *event,
267 AbsoluteTime deadline, UInt32 interType)
b0d623f7 268{
0a7de745
A
269 _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
270 UInt32 count = lock->count;
271 int res;
272
273 assert(lock->thread == IOThreadSelf());
274
275 lock->count = 0;
cb323159 276 lock->thread = NULL;
0a7de745
A
277 res = lck_mtx_sleep_deadline(&lock->mutex, LCK_SLEEP_PROMOTED_PRI, (event_t) event,
278 (wait_interrupt_t) interType, __OSAbsoluteTime(deadline));
279
280 // Must re-establish the recursive lock no matter why we woke up
281 // otherwise we would potentially leave the return path corrupted.
cb323159 282 assert(lock->thread == NULL);
0a7de745
A
283 assert(lock->count == 0);
284 lock->thread = IOThreadSelf();
285 lock->count = count;
286 return res;
1c79356b
A
287}
288
0a7de745
A
289void
290IORecursiveLockWakeup(IORecursiveLock *, void *event, bool oneThread)
1c79356b 291{
0a7de745 292 thread_wakeup_prim((event_t) event, oneThread, THREAD_AWAKENED);
1c79356b
A
293}
294
295/*
296 * Complex (read/write) lock operations
297 */
298
0a7de745
A
299IORWLock *
300IORWLockAlloc( void )
1c79356b 301{
0a7de745 302 return lck_rw_alloc_init(IOLockGroup, LCK_ATTR_NULL);
1c79356b
A
303}
304
0a7de745
A
305void
306IORWLockFree( IORWLock * lock)
1c79356b 307{
0a7de745 308 lck_rw_free( lock, IOLockGroup);
91447636
A
309}
310
0a7de745
A
311lck_rw_t *
312IORWLockGetMachLock( IORWLock * lock)
91447636 313{
0a7de745 314 return (lck_rw_t *)lock;
1c79356b
A
315}
316
317
318/*
319 * Spin locks
320 */
321
0a7de745
A
322IOSimpleLock *
323IOSimpleLockAlloc( void )
1c79356b 324{
0a7de745 325 return lck_spin_alloc_init( IOLockGroup, LCK_ATTR_NULL);
1c79356b
A
326}
327
0a7de745
A
328void
329IOSimpleLockInit( IOSimpleLock * lock)
1c79356b 330{
0a7de745 331 lck_spin_init( lock, IOLockGroup, LCK_ATTR_NULL);
1c79356b
A
332}
333
cb323159
A
334void
335IOSimpleLockDestroy( IOSimpleLock * lock )
336{
337 lck_spin_destroy(lock, IOLockGroup);
338}
339
0a7de745
A
340void
341IOSimpleLockFree( IOSimpleLock * lock )
1c79356b 342{
0a7de745 343 lck_spin_free( lock, IOLockGroup);
91447636
A
344}
345
0a7de745
A
346lck_spin_t *
347IOSimpleLockGetMachLock( IOSimpleLock * lock)
91447636 348{
0a7de745 349 return (lck_spin_t *)lock;
1c79356b
A
350}
351
5c9f4661
A
352#ifndef IOLOCKS_INLINE
353/*
354 * Lock assertions
355 */
356
357void
358IOLockAssert(IOLock * lock, IOLockAssertState type)
359{
0a7de745 360 LCK_MTX_ASSERT(lock, type);
5c9f4661
A
361}
362
363void
364IORWLockAssert(IORWLock * lock, IORWLockAssertState type)
365{
0a7de745 366 LCK_RW_ASSERT(lock, type);
5c9f4661
A
367}
368
369void
370IOSimpleLockAssert(IOSimpleLock *lock, IOSimpleLockAssertState type)
371{
0a7de745 372 LCK_SPIN_ASSERT(l, type);
5c9f4661
A
373}
374#endif /* !IOLOCKS_INLINE */
1c79356b 375} /* extern "C" */