1*043036a2SApple OSS Distributions /*
2*043036a2SApple OSS Distributions * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
3*043036a2SApple OSS Distributions *
4*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*043036a2SApple OSS Distributions *
6*043036a2SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*043036a2SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*043036a2SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*043036a2SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*043036a2SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*043036a2SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*043036a2SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*043036a2SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*043036a2SApple OSS Distributions *
15*043036a2SApple OSS Distributions * Please obtain a copy of the License at
16*043036a2SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*043036a2SApple OSS Distributions *
18*043036a2SApple OSS Distributions * The Original Code and all software distributed under the License are
19*043036a2SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*043036a2SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*043036a2SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*043036a2SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*043036a2SApple OSS Distributions * Please see the License for the specific language governing rights and
24*043036a2SApple OSS Distributions * limitations under the License.
25*043036a2SApple OSS Distributions *
26*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*043036a2SApple OSS Distributions */
28*043036a2SApple OSS Distributions /*
29*043036a2SApple OSS Distributions *
30*043036a2SApple OSS Distributions */
31*043036a2SApple OSS Distributions
32*043036a2SApple OSS Distributions #ifndef __IOKIT_IOLOCKS_H
33*043036a2SApple OSS Distributions #define __IOKIT_IOLOCKS_H
34*043036a2SApple OSS Distributions
35*043036a2SApple OSS Distributions #ifndef KERNEL
36*043036a2SApple OSS Distributions #error IOLocks.h is for kernel use only
37*043036a2SApple OSS Distributions #endif
38*043036a2SApple OSS Distributions
39*043036a2SApple OSS Distributions #include <sys/appleapiopts.h>
40*043036a2SApple OSS Distributions #include <sys/cdefs.h>
41*043036a2SApple OSS Distributions
42*043036a2SApple OSS Distributions #include <IOKit/system.h>
43*043036a2SApple OSS Distributions
44*043036a2SApple OSS Distributions #include <IOKit/IOReturn.h>
45*043036a2SApple OSS Distributions #include <IOKit/IOTypes.h>
46*043036a2SApple OSS Distributions #include <machine/machine_routines.h>
47*043036a2SApple OSS Distributions #include <libkern/locks.h>
48*043036a2SApple OSS Distributions
49*043036a2SApple OSS Distributions #ifdef __cplusplus
50*043036a2SApple OSS Distributions extern "C" {
51*043036a2SApple OSS Distributions #endif
52*043036a2SApple OSS Distributions
53*043036a2SApple OSS Distributions /*! @var IOLockGroup
54*043036a2SApple OSS Distributions * Global lock group used by all IOKit locks. To simplify kext debugging and lock-heat analysis, consider using lck_* locks with a per-driver lock group, as defined in kern/locks.h.
55*043036a2SApple OSS Distributions */
56*043036a2SApple OSS Distributions extern lck_grp_t *IOLockGroup;
57*043036a2SApple OSS Distributions
58*043036a2SApple OSS Distributions #if defined(XNU_KERNEL_PRIVATE)
59*043036a2SApple OSS Distributions #define IOLOCKS_INLINE 1
60*043036a2SApple OSS Distributions #endif
61*043036a2SApple OSS Distributions
62*043036a2SApple OSS Distributions /*
63*043036a2SApple OSS Distributions * Mutex lock operations
64*043036a2SApple OSS Distributions */
65*043036a2SApple OSS Distributions
66*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
67*043036a2SApple OSS Distributions typedef lck_mtx_t IOLock;
68*043036a2SApple OSS Distributions #else
69*043036a2SApple OSS Distributions typedef struct _IOLock IOLock;
70*043036a2SApple OSS Distributions #endif /* IOLOCKS_INLINE */
71*043036a2SApple OSS Distributions
72*043036a2SApple OSS Distributions
73*043036a2SApple OSS Distributions /*! @function IOLockAlloc
74*043036a2SApple OSS Distributions * @abstract Allocates and initializes a mutex.
75*043036a2SApple OSS Distributions * @discussion Allocates a mutex in general purpose memory, and initializes it. Mutexes are general purpose blocking mutual exclusion locks, supplied by libkern/locks.h. This function may block and so should not be called from interrupt level or while a spin lock is held. IOLocks use the global IOKit lock group, IOLockGroup. To simplify kext debugging and lock-heat analysis, consider using lck_* locks with a per-driver lock group, as defined in kern/locks.h.
76*043036a2SApple OSS Distributions * @result Pointer to the allocated lock, or zero on failure. */
77*043036a2SApple OSS Distributions
78*043036a2SApple OSS Distributions IOLock * IOLockAlloc( void );
79*043036a2SApple OSS Distributions
80*043036a2SApple OSS Distributions /*! @function IOLockFree
81*043036a2SApple OSS Distributions * @abstract Frees a mutex.
82*043036a2SApple OSS Distributions * @discussion Frees a lock allocated with IOLockAlloc. Mutex should be unlocked with no waiters.
83*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
84*043036a2SApple OSS Distributions
85*043036a2SApple OSS Distributions void IOLockFree( IOLock * lock);
86*043036a2SApple OSS Distributions
87*043036a2SApple OSS Distributions /*! @function IOLockGetMachLock
88*043036a2SApple OSS Distributions * @abstract Accessor to a Mach mutex.
89*043036a2SApple OSS Distributions * @discussion Accessor to the Mach mutex.
90*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
91*043036a2SApple OSS Distributions
92*043036a2SApple OSS Distributions lck_mtx_t * IOLockGetMachLock( IOLock * lock);
93*043036a2SApple OSS Distributions
94*043036a2SApple OSS Distributions /*! @function IOLockLock
95*043036a2SApple OSS Distributions * @abstract Lock a mutex.
96*043036a2SApple OSS Distributions * @discussion Lock the mutex. If the lock is held by any thread, block waiting for its unlock. This function may block and so should not be called from interrupt level or while a spin lock is held. Locking the mutex recursively from one thread will result in deadlock.
97*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
98*043036a2SApple OSS Distributions
99*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
100*043036a2SApple OSS Distributions #define IOLockLock(l) lck_mtx_lock(l)
101*043036a2SApple OSS Distributions #else
102*043036a2SApple OSS Distributions void IOLockLock( IOLock * lock);
103*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
104*043036a2SApple OSS Distributions
105*043036a2SApple OSS Distributions /*! @function IOLockTryLock
106*043036a2SApple OSS Distributions * @abstract Attempt to lock a mutex.
107*043036a2SApple OSS Distributions * @discussion Lock the mutex if it is currently unlocked, and return true. If the lock is held by any thread, return false.
108*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock.
109*043036a2SApple OSS Distributions * @result True if the mutex was unlocked and is now locked by the caller, otherwise false. */
110*043036a2SApple OSS Distributions
111*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
112*043036a2SApple OSS Distributions #define IOLockTryLock(l) lck_mtx_try_lock(l)
113*043036a2SApple OSS Distributions #else
114*043036a2SApple OSS Distributions boolean_t IOLockTryLock( IOLock * lock);
115*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
116*043036a2SApple OSS Distributions
117*043036a2SApple OSS Distributions /*! @function IOLockUnlock
118*043036a2SApple OSS Distributions * @abstract Unlock a mutex.
119*043036a2SApple OSS Distributions * @discussion Unlock the mutex and wake any blocked waiters. Results are undefined if the caller has not locked the mutex. This function may block and so should not be called from interrupt level or while a spin lock is held.
120*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
121*043036a2SApple OSS Distributions
122*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
123*043036a2SApple OSS Distributions #define IOLockUnlock(l) lck_mtx_unlock(l)
124*043036a2SApple OSS Distributions #else
125*043036a2SApple OSS Distributions void IOLockUnlock( IOLock * lock);
126*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
127*043036a2SApple OSS Distributions
128*043036a2SApple OSS Distributions /*! @function IOLockSleep
129*043036a2SApple OSS Distributions * @abstract Sleep with mutex unlock and relock
130*043036a2SApple OSS Distributions * @discussion Prepare to sleep,unlock the mutex, and re-acquire it on wakeup. Results are undefined if the caller has not locked the mutex. This function may block and so should not be called from interrupt level or while a spin lock is held.
131*043036a2SApple OSS Distributions * @param lock Pointer to the locked lock.
132*043036a2SApple OSS Distributions * @param event The event to sleep on. Must be non-NULL.
133*043036a2SApple OSS Distributions * @param interType How can the sleep be interrupted.
134*043036a2SApple OSS Distributions * @result The wait-result value indicating how the thread was awakened.*/
135*043036a2SApple OSS Distributions int IOLockSleep( IOLock * lock, void *event, UInt32 interType) __DARWIN14_ALIAS(IOLockSleep);
136*043036a2SApple OSS Distributions
137*043036a2SApple OSS Distributions int IOLockSleepDeadline( IOLock * lock, void *event,
138*043036a2SApple OSS Distributions AbsoluteTime deadline, UInt32 interType) __DARWIN14_ALIAS(IOLockSleepDeadline);
139*043036a2SApple OSS Distributions
140*043036a2SApple OSS Distributions void IOLockWakeup(IOLock * lock, void *event, bool oneThread) __DARWIN14_ALIAS(IOLockWakeup);
141*043036a2SApple OSS Distributions
142*043036a2SApple OSS Distributions #ifdef XNU_KERNEL_PRIVATE
143*043036a2SApple OSS Distributions /*! @enum IOLockAssertState
144*043036a2SApple OSS Distributions * @abstract Used with IOLockAssert to assert the state of a lock.
145*043036a2SApple OSS Distributions */
146*043036a2SApple OSS Distributions typedef enum {
147*043036a2SApple OSS Distributions kIOLockAssertOwned = LCK_ASSERT_OWNED,
148*043036a2SApple OSS Distributions kIOLockAssertNotOwned = LCK_ASSERT_NOTOWNED
149*043036a2SApple OSS Distributions } IOLockAssertState;
150*043036a2SApple OSS Distributions
151*043036a2SApple OSS Distributions int IOLockSleepWithInheritor( IOLock * lock, UInt32 lck_sleep_action,
152*043036a2SApple OSS Distributions void *event, thread_t inheritor, UInt32 interType, uint64_t deadline);
153*043036a2SApple OSS Distributions
154*043036a2SApple OSS Distributions void IOLockWakeupAllWithInheritor(IOLock * lock, void *event);
155*043036a2SApple OSS Distributions
156*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
157*043036a2SApple OSS Distributions #define IOLockAssert(l, type) LCK_MTX_ASSERT(l, type)
158*043036a2SApple OSS Distributions
159*043036a2SApple OSS Distributions /*! @function IOLockInlineInit()
160*043036a2SApple OSS Distributions * @abstract Initializes an inline lock.
161*043036a2SApple OSS Distributions */
162*043036a2SApple OSS Distributions void IOLockInlineInit(IOLock *);
163*043036a2SApple OSS Distributions
164*043036a2SApple OSS Distributions /*! @function IOLockInlineDestroy()
165*043036a2SApple OSS Distributions * @abstract Destroys an inline lock.
166*043036a2SApple OSS Distributions */
167*043036a2SApple OSS Distributions void IOLockInlineDestroy(IOLock *);
168*043036a2SApple OSS Distributions
169*043036a2SApple OSS Distributions #else
170*043036a2SApple OSS Distributions /*! @function IOLockAssert
171*043036a2SApple OSS Distributions * @abstract Assert that lock is either held or not held by current thread.
172*043036a2SApple OSS Distributions * @discussion Call with either kIOLockAssertOwned or kIOLockAssertNotOwned.
173*043036a2SApple OSS Distributions * Panics the kernel if the lock is not owned if called with kIOLockAssertOwned,
174*043036a2SApple OSS Distributions * and vice-versa.
175*043036a2SApple OSS Distributions */
176*043036a2SApple OSS Distributions void IOLockAssert(IOLock * lock, IOLockAssertState type);
177*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
178*043036a2SApple OSS Distributions #endif /* !XNU_KERNEL_PRIVATE */
179*043036a2SApple OSS Distributions
180*043036a2SApple OSS Distributions #ifdef __APPLE_API_OBSOLETE
181*043036a2SApple OSS Distributions
182*043036a2SApple OSS Distributions /* The following API is deprecated */
183*043036a2SApple OSS Distributions
184*043036a2SApple OSS Distributions typedef enum {
185*043036a2SApple OSS Distributions kIOLockStateUnlocked = 0,
186*043036a2SApple OSS Distributions kIOLockStateLocked = 1
187*043036a2SApple OSS Distributions } IOLockState;
188*043036a2SApple OSS Distributions
189*043036a2SApple OSS Distributions void IOLockInitWithState( IOLock * lock, IOLockState state);
190*043036a2SApple OSS Distributions #define IOLockInit( l ) IOLockInitWithState( l, kIOLockStateUnlocked);
191*043036a2SApple OSS Distributions
192*043036a2SApple OSS Distributions static __inline__ void
IOTakeLock(IOLock * lock)193*043036a2SApple OSS Distributions IOTakeLock( IOLock * lock)
194*043036a2SApple OSS Distributions {
195*043036a2SApple OSS Distributions IOLockLock(lock);
196*043036a2SApple OSS Distributions }
197*043036a2SApple OSS Distributions static __inline__ boolean_t
IOTryLock(IOLock * lock)198*043036a2SApple OSS Distributions IOTryLock( IOLock * lock)
199*043036a2SApple OSS Distributions {
200*043036a2SApple OSS Distributions return IOLockTryLock(lock);
201*043036a2SApple OSS Distributions }
202*043036a2SApple OSS Distributions static __inline__ void
IOUnlock(IOLock * lock)203*043036a2SApple OSS Distributions IOUnlock( IOLock * lock)
204*043036a2SApple OSS Distributions {
205*043036a2SApple OSS Distributions IOLockUnlock(lock);
206*043036a2SApple OSS Distributions }
207*043036a2SApple OSS Distributions
208*043036a2SApple OSS Distributions #endif /* __APPLE_API_OBSOLETE */
209*043036a2SApple OSS Distributions
210*043036a2SApple OSS Distributions /*
211*043036a2SApple OSS Distributions * Recursive lock operations
212*043036a2SApple OSS Distributions */
213*043036a2SApple OSS Distributions
214*043036a2SApple OSS Distributions typedef struct _IORecursiveLock IORecursiveLock;
215*043036a2SApple OSS Distributions
216*043036a2SApple OSS Distributions /*! @function IORecursiveLockAlloc
217*043036a2SApple OSS Distributions * @abstract Allocates and initializes an recursive lock.
218*043036a2SApple OSS Distributions * @discussion Allocates a recursive lock in general purpose memory, and initializes it. Recursive locks function identically to mutexes but allow one thread to lock more than once, with balanced unlocks. IORecursiveLocks use the global IOKit lock group, IOLockGroup. To simplify kext debugging and lock-heat analysis, consider using lck_* locks with a per-driver lock group, as defined in kern/locks.h.
219*043036a2SApple OSS Distributions * @result Pointer to the allocated lock, or zero on failure. */
220*043036a2SApple OSS Distributions
221*043036a2SApple OSS Distributions IORecursiveLock * IORecursiveLockAlloc( void );
222*043036a2SApple OSS Distributions
223*043036a2SApple OSS Distributions /*! @function IORecursiveLockFree
224*043036a2SApple OSS Distributions * @abstract Frees a recursive lock.
225*043036a2SApple OSS Distributions * @discussion Frees a lock allocated with IORecursiveLockAlloc. Lock should be unlocked with no waiters.
226*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
227*043036a2SApple OSS Distributions
228*043036a2SApple OSS Distributions void IORecursiveLockFree( IORecursiveLock * lock);
229*043036a2SApple OSS Distributions
230*043036a2SApple OSS Distributions /*! @function IORecursiveLockGetMachLock
231*043036a2SApple OSS Distributions * @abstract Accessor to a Mach mutex.
232*043036a2SApple OSS Distributions * @discussion Accessor to the Mach mutex.
233*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
234*043036a2SApple OSS Distributions
235*043036a2SApple OSS Distributions lck_mtx_t * IORecursiveLockGetMachLock( IORecursiveLock * lock);
236*043036a2SApple OSS Distributions
237*043036a2SApple OSS Distributions /*! @function IORecursiveLockLock
238*043036a2SApple OSS Distributions * @abstract Lock a recursive lock.
239*043036a2SApple OSS Distributions * @discussion Lock the recursive lock. If the lock is held by another thread, block waiting for its unlock. This function may block and so should not be called from interrupt level or while a spin lock is held. The lock may be taken recursively by the same thread, with a balanced number of calls to IORecursiveLockUnlock.
240*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
241*043036a2SApple OSS Distributions
242*043036a2SApple OSS Distributions void IORecursiveLockLock( IORecursiveLock * lock);
243*043036a2SApple OSS Distributions
244*043036a2SApple OSS Distributions /*! @function IORecursiveLockTryLock
245*043036a2SApple OSS Distributions * @abstract Attempt to lock a recursive lock.
246*043036a2SApple OSS Distributions * @discussion Lock the lock if it is currently unlocked, or held by the calling thread, and return true. If the lock is held by another thread, return false. Successful calls to IORecursiveLockTryLock should be balanced with calls to IORecursiveLockUnlock.
247*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock.
248*043036a2SApple OSS Distributions * @result True if the lock is now locked by the caller, otherwise false. */
249*043036a2SApple OSS Distributions
250*043036a2SApple OSS Distributions boolean_t IORecursiveLockTryLock( IORecursiveLock * lock);
251*043036a2SApple OSS Distributions
252*043036a2SApple OSS Distributions /*! @function IORecursiveLockUnlock
253*043036a2SApple OSS Distributions * @abstract Unlock a recursive lock.
254*043036a2SApple OSS Distributions * @discussion Undo one call to IORecursiveLockLock, if the lock is now unlocked wake any blocked waiters. Results are undefined if the caller does not balance calls to IORecursiveLockLock with IORecursiveLockUnlock. This function may block and so should not be called from interrupt level or while a spin lock is held.
255*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
256*043036a2SApple OSS Distributions
257*043036a2SApple OSS Distributions void IORecursiveLockUnlock( IORecursiveLock * lock);
258*043036a2SApple OSS Distributions
259*043036a2SApple OSS Distributions /*! @function IORecursiveLockHaveLock
260*043036a2SApple OSS Distributions * @abstract Check if a recursive lock is held by the calling thread.
261*043036a2SApple OSS Distributions * @discussion If the lock is held by the calling thread, return true, otherwise the lock is unlocked, or held by another thread and false is returned.
262*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock.
263*043036a2SApple OSS Distributions * @result True if the calling thread holds the lock otherwise false. */
264*043036a2SApple OSS Distributions
265*043036a2SApple OSS Distributions boolean_t IORecursiveLockHaveLock( const IORecursiveLock * lock);
266*043036a2SApple OSS Distributions
267*043036a2SApple OSS Distributions extern int IORecursiveLockSleep( IORecursiveLock *_lock,
268*043036a2SApple OSS Distributions void *event, UInt32 interType);
269*043036a2SApple OSS Distributions extern int IORecursiveLockSleepDeadline( IORecursiveLock * _lock, void *event,
270*043036a2SApple OSS Distributions AbsoluteTime deadline, UInt32 interType);
271*043036a2SApple OSS Distributions extern void IORecursiveLockWakeup( IORecursiveLock *_lock,
272*043036a2SApple OSS Distributions void *event, bool oneThread);
273*043036a2SApple OSS Distributions
274*043036a2SApple OSS Distributions /*
275*043036a2SApple OSS Distributions * Complex (read/write) lock operations
276*043036a2SApple OSS Distributions */
277*043036a2SApple OSS Distributions
278*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
279*043036a2SApple OSS Distributions typedef lck_rw_t IORWLock;
280*043036a2SApple OSS Distributions #else
281*043036a2SApple OSS Distributions typedef struct _IORWLock IORWLock;
282*043036a2SApple OSS Distributions #endif /* IOLOCKS_INLINE */
283*043036a2SApple OSS Distributions
284*043036a2SApple OSS Distributions /*! @function IORWLockAlloc
285*043036a2SApple OSS Distributions * @abstract Allocates and initializes a read/write lock.
286*043036a2SApple OSS Distributions * @discussion Allocates and initializes a read/write lock in general purpose memory. Read/write locks provide for multiple readers, one exclusive writer, and are supplied by libkern/locks.h. This function may block and so should not be called from interrupt level or while a spin lock is held. IORWLocks use the global IOKit lock group, IOLockGroup. To simplify kext debugging and lock-heat analysis, consider using lck_* locks with a per-driver lock group, as defined in kern/locks.h.
287*043036a2SApple OSS Distributions * @result Pointer to the allocated lock, or zero on failure. */
288*043036a2SApple OSS Distributions
289*043036a2SApple OSS Distributions IORWLock * IORWLockAlloc( void );
290*043036a2SApple OSS Distributions
291*043036a2SApple OSS Distributions /*! @function IORWLockFree
292*043036a2SApple OSS Distributions * @abstract Frees a read/write lock.
293*043036a2SApple OSS Distributions * @discussion Frees a lock allocated with IORWLockAlloc. Lock should be unlocked with no waiters.
294*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
295*043036a2SApple OSS Distributions
296*043036a2SApple OSS Distributions void IORWLockFree( IORWLock * lock);
297*043036a2SApple OSS Distributions
298*043036a2SApple OSS Distributions /*! @function IORWLockGetMachLock
299*043036a2SApple OSS Distributions * @abstract Accessor to a Mach read/write lock.
300*043036a2SApple OSS Distributions * @discussion Accessor to the Mach read/write lock.
301*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
302*043036a2SApple OSS Distributions
303*043036a2SApple OSS Distributions lck_rw_t * IORWLockGetMachLock( IORWLock * lock);
304*043036a2SApple OSS Distributions
305*043036a2SApple OSS Distributions /*! @function IORWLockRead
306*043036a2SApple OSS Distributions * @abstract Lock a read/write lock for read.
307*043036a2SApple OSS Distributions * @discussion Lock the lock for read, allowing multiple readers when there are no writers. If the lock is held for write, block waiting for its unlock. This function may block and so should not be called from interrupt level or while a spin lock is held. Locking the lock recursively from one thread, for read or write, can result in deadlock.
308*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
309*043036a2SApple OSS Distributions
310*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
311*043036a2SApple OSS Distributions #define IORWLockRead(l) lck_rw_lock_shared(l)
312*043036a2SApple OSS Distributions #else
313*043036a2SApple OSS Distributions void IORWLockRead(IORWLock * lock);
314*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
315*043036a2SApple OSS Distributions
316*043036a2SApple OSS Distributions /*! @function IORWLockTryRead
317*043036a2SApple OSS Distributions * @abstract Attempt to lock a read/write lock for read.
318*043036a2SApple OSS Distributions * @discussion Lock the lock for read, allowing multiple readers when there are no writers. If the lock is held for write, return false. Return true otherwise.
319*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
320*043036a2SApple OSS Distributions
321*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
322*043036a2SApple OSS Distributions #define IORWLockTryRead(l) lck_rw_try_lock_shared(l)
323*043036a2SApple OSS Distributions #else
324*043036a2SApple OSS Distributions void IORWLockTryRead( IORWLock * lock);
325*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
326*043036a2SApple OSS Distributions
327*043036a2SApple OSS Distributions /*! @function IORWLockWrite
328*043036a2SApple OSS Distributions * @abstract Lock a read/write lock for write.
329*043036a2SApple OSS Distributions * @discussion Lock the lock for write, allowing one writer exlusive access. If the lock is held for read or write, block waiting for its unlock. This function may block and so should not be called from interrupt level or while a spin lock is held. Locking the lock recursively from one thread, for read or write, can result in deadlock.
330*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
331*043036a2SApple OSS Distributions
332*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
333*043036a2SApple OSS Distributions #define IORWLockWrite(l) lck_rw_lock_exclusive(l)
334*043036a2SApple OSS Distributions #else
335*043036a2SApple OSS Distributions void IORWLockWrite( IORWLock * lock);
336*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
337*043036a2SApple OSS Distributions
338*043036a2SApple OSS Distributions /*! @function IORWLockTryWrite
339*043036a2SApple OSS Distributions * @abstract Attempt to lock a read/write lock for write.
340*043036a2SApple OSS Distributions * @discussion Lock the lock for write, allowing one writer exlusive access. If the lock is held for read or write, return false. Return true otherwise.
341*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
342*043036a2SApple OSS Distributions
343*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
344*043036a2SApple OSS Distributions #define IORWLockTryWrite(l) lck_rw_try_lock_exclusive(l)
345*043036a2SApple OSS Distributions #else
346*043036a2SApple OSS Distributions void IORWLockTryWrite( IORWLock * lock);
347*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
348*043036a2SApple OSS Distributions
349*043036a2SApple OSS Distributions /*! @function IORWLockUnlock
350*043036a2SApple OSS Distributions * @abstract Unlock a read/write lock.
351*043036a2SApple OSS Distributions * @discussion Undo one call to IORWLockRead or IORWLockWrite. Results are undefined if the caller has not locked the lock. This function may block and so should not be called from interrupt level or while a spin lock is held.
352*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
353*043036a2SApple OSS Distributions
354*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
355*043036a2SApple OSS Distributions #define IORWLockUnlock(l) lck_rw_done(l)
356*043036a2SApple OSS Distributions #else
357*043036a2SApple OSS Distributions void IORWLockUnlock( IORWLock * lock);
358*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
359*043036a2SApple OSS Distributions
360*043036a2SApple OSS Distributions #ifdef XNU_KERNEL_PRIVATE
361*043036a2SApple OSS Distributions /*! @enum IORWLockAssertState
362*043036a2SApple OSS Distributions * @abstract Used with IORWLockAssert to assert the state of a lock.
363*043036a2SApple OSS Distributions */
364*043036a2SApple OSS Distributions typedef enum {
365*043036a2SApple OSS Distributions kIORWLockAssertRead = LCK_RW_ASSERT_SHARED,
366*043036a2SApple OSS Distributions kIORWLockAssertWrite = LCK_RW_ASSERT_EXCLUSIVE,
367*043036a2SApple OSS Distributions kIORWLockAssertHeld = LCK_RW_ASSERT_HELD,
368*043036a2SApple OSS Distributions kIORWLockAssertNotHeld = LCK_RW_ASSERT_NOTHELD
369*043036a2SApple OSS Distributions } IORWLockAssertState;
370*043036a2SApple OSS Distributions
371*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
372*043036a2SApple OSS Distributions #define IORWLockAssert(l, type) LCK_RW_ASSERT(l, type)
373*043036a2SApple OSS Distributions
374*043036a2SApple OSS Distributions /*! @function IORWLockInlineInit()
375*043036a2SApple OSS Distributions * @abstract Initializes an inline lock.
376*043036a2SApple OSS Distributions */
377*043036a2SApple OSS Distributions void IORWLockInlineInit(IORWLock *);
378*043036a2SApple OSS Distributions
379*043036a2SApple OSS Distributions /*! @function IORWLockInlineDestroy()
380*043036a2SApple OSS Distributions * @abstract Destroys an inline lock.
381*043036a2SApple OSS Distributions */
382*043036a2SApple OSS Distributions void IORWLockInlineDestroy(IORWLock *);
383*043036a2SApple OSS Distributions
384*043036a2SApple OSS Distributions #else
385*043036a2SApple OSS Distributions /*! @function IORWLockAssert
386*043036a2SApple OSS Distributions * @abstract Assert that a reader-writer lock is either held or not held
387*043036a2SApple OSS Distributions * by the current thread.
388*043036a2SApple OSS Distributions * @discussion Call with a value defined by the IORWLockAssertState type.
389*043036a2SApple OSS Distributions * If the specified lock is not in the state specified by the type argument,
390*043036a2SApple OSS Distributions * then the kernel will panic.
391*043036a2SApple OSS Distributions */
392*043036a2SApple OSS Distributions void IORWLockAssert(IORWLock * lock, IORWLockAssertState type);
393*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
394*043036a2SApple OSS Distributions #endif /* !XNU_KERNEL_PRIVATE */
395*043036a2SApple OSS Distributions
396*043036a2SApple OSS Distributions #ifdef __APPLE_API_OBSOLETE
397*043036a2SApple OSS Distributions
398*043036a2SApple OSS Distributions /* The following API is deprecated */
399*043036a2SApple OSS Distributions
400*043036a2SApple OSS Distributions static __inline__ void
IOReadLock(IORWLock * lock)401*043036a2SApple OSS Distributions IOReadLock( IORWLock * lock)
402*043036a2SApple OSS Distributions {
403*043036a2SApple OSS Distributions IORWLockRead(lock);
404*043036a2SApple OSS Distributions }
405*043036a2SApple OSS Distributions static __inline__ void
IOWriteLock(IORWLock * lock)406*043036a2SApple OSS Distributions IOWriteLock( IORWLock * lock)
407*043036a2SApple OSS Distributions {
408*043036a2SApple OSS Distributions IORWLockWrite(lock);
409*043036a2SApple OSS Distributions }
410*043036a2SApple OSS Distributions static __inline__ void
IORWUnlock(IORWLock * lock)411*043036a2SApple OSS Distributions IORWUnlock( IORWLock * lock)
412*043036a2SApple OSS Distributions {
413*043036a2SApple OSS Distributions IORWLockUnlock(lock);
414*043036a2SApple OSS Distributions }
415*043036a2SApple OSS Distributions
416*043036a2SApple OSS Distributions #endif /* __APPLE_API_OBSOLETE */
417*043036a2SApple OSS Distributions
418*043036a2SApple OSS Distributions
419*043036a2SApple OSS Distributions /*
420*043036a2SApple OSS Distributions * Simple locks. Cannot block while holding a simple lock.
421*043036a2SApple OSS Distributions */
422*043036a2SApple OSS Distributions
423*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
424*043036a2SApple OSS Distributions typedef lck_spin_t IOSimpleLock;
425*043036a2SApple OSS Distributions #else
426*043036a2SApple OSS Distributions typedef struct _IOSimpleLock IOSimpleLock;
427*043036a2SApple OSS Distributions #endif /* IOLOCKS_INLINE */
428*043036a2SApple OSS Distributions
429*043036a2SApple OSS Distributions /*! @function IOSimpleLockAlloc
430*043036a2SApple OSS Distributions * @abstract Allocates and initializes a spin lock.
431*043036a2SApple OSS Distributions * @discussion Allocates and initializes a spin lock in general purpose memory. Spin locks provide non-blocking mutual exclusion for synchronization between thread context and interrupt context, or for multiprocessor synchronization, and are supplied by libkern/locks.h. This function may block and so should not be called from interrupt level or while a spin lock is held. IOSimpleLocks use the global IOKit lock group, IOLockGroup. To simplify kext debugging and lock-heat analysis, consider using lck_* locks with a per-driver lock group, as defined in kern/locks.h.
432*043036a2SApple OSS Distributions * @result Pointer to the allocated lock, or zero on failure. */
433*043036a2SApple OSS Distributions
434*043036a2SApple OSS Distributions IOSimpleLock * IOSimpleLockAlloc( void );
435*043036a2SApple OSS Distributions
436*043036a2SApple OSS Distributions /*! @function IOSimpleLockFree
437*043036a2SApple OSS Distributions * @abstract Frees a spin lock.
438*043036a2SApple OSS Distributions * @discussion Frees a lock allocated with IOSimpleLockAlloc.
439*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
440*043036a2SApple OSS Distributions
441*043036a2SApple OSS Distributions void IOSimpleLockFree( IOSimpleLock * lock );
442*043036a2SApple OSS Distributions
443*043036a2SApple OSS Distributions /*! @function IOSimpleLockGetMachLock
444*043036a2SApple OSS Distributions * @abstract Accessor to a Mach spin lock.
445*043036a2SApple OSS Distributions * @discussion Accessor to the Mach spin lock.
446*043036a2SApple OSS Distributions * @param lock Pointer to the allocated lock. */
447*043036a2SApple OSS Distributions
448*043036a2SApple OSS Distributions lck_spin_t * IOSimpleLockGetMachLock( IOSimpleLock * lock);
449*043036a2SApple OSS Distributions
450*043036a2SApple OSS Distributions /*! @function IOSimpleLockInit
451*043036a2SApple OSS Distributions * @abstract Initialize a spin lock.
452*043036a2SApple OSS Distributions * @discussion Initialize a non heap allocated spin lock to the unlocked state. Use this function when your lock is, for example, a member variable. You will need to call IOSimpleLockDestroy when you are finished with the lock to avoid lock group refcount leaks.
453*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
454*043036a2SApple OSS Distributions
455*043036a2SApple OSS Distributions void IOSimpleLockInit( IOSimpleLock * lock );
456*043036a2SApple OSS Distributions
457*043036a2SApple OSS Distributions /*! @function IOSimpleLockDestroy
458*043036a2SApple OSS Distributions * @abstract De-initializes (destroys) a spin lock initialized with IOSimpleLockInit
459*043036a2SApple OSS Distributions * @discussion Destroy / De-initialize a non heap allocated spin lock, releasing any system resources such as lock group refcounts.
460*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
461*043036a2SApple OSS Distributions
462*043036a2SApple OSS Distributions void IOSimpleLockDestroy( IOSimpleLock * lock );
463*043036a2SApple OSS Distributions
464*043036a2SApple OSS Distributions /*! @function IOSimpleLockLock
465*043036a2SApple OSS Distributions * @abstract Lock a spin lock.
466*043036a2SApple OSS Distributions * @discussion Lock the spin lock. If the lock is held, spin waiting for its unlock. Spin locks disable preemption, cannot be held across any blocking operation, and should be held for very short periods. When used to synchronize between interrupt context and thread context they should be locked with interrupts disabled - IOSimpleLockLockDisableInterrupt() will do both. Locking the lock recursively from one thread will result in deadlock.
467*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
468*043036a2SApple OSS Distributions
469*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
470*043036a2SApple OSS Distributions #define IOSimpleLockLock(l) lck_spin_lock(l)
471*043036a2SApple OSS Distributions #else
472*043036a2SApple OSS Distributions void IOSimpleLockLock( IOSimpleLock * lock );
473*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
474*043036a2SApple OSS Distributions
475*043036a2SApple OSS Distributions
476*043036a2SApple OSS Distributions /*! @function IOSimpleLockTryLock
477*043036a2SApple OSS Distributions * @abstract Attempt to lock a spin lock.
478*043036a2SApple OSS Distributions * @discussion Lock the spin lock if it is currently unlocked, and return true. If the lock is held, return false. Successful calls to IOSimpleLockTryLock should be balanced with calls to IOSimpleLockUnlock.
479*043036a2SApple OSS Distributions * @param lock Pointer to the lock.
480*043036a2SApple OSS Distributions * @result True if the lock was unlocked and is now locked by the caller, otherwise false. */
481*043036a2SApple OSS Distributions
482*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
483*043036a2SApple OSS Distributions #define IOSimpleLockTryLock(l) lck_spin_try_lock(l)
484*043036a2SApple OSS Distributions #else
485*043036a2SApple OSS Distributions boolean_t IOSimpleLockTryLock( IOSimpleLock * lock );
486*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
487*043036a2SApple OSS Distributions
488*043036a2SApple OSS Distributions /*! @function IOSimpleLockUnlock
489*043036a2SApple OSS Distributions * @abstract Unlock a spin lock.
490*043036a2SApple OSS Distributions * @discussion Unlock the lock, and restore preemption. Results are undefined if the caller has not locked the lock.
491*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
492*043036a2SApple OSS Distributions
493*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
494*043036a2SApple OSS Distributions #define IOSimpleLockUnlock(l) lck_spin_unlock(l)
495*043036a2SApple OSS Distributions #else
496*043036a2SApple OSS Distributions void IOSimpleLockUnlock( IOSimpleLock * lock );
497*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
498*043036a2SApple OSS Distributions
499*043036a2SApple OSS Distributions #ifdef XNU_KERNEL_PRIVATE
500*043036a2SApple OSS Distributions /*! @enum IOSimpleLockAssertState
501*043036a2SApple OSS Distributions * @abstract Used with IOSimpleLockAssert to assert the state of a lock.
502*043036a2SApple OSS Distributions */
503*043036a2SApple OSS Distributions typedef enum {
504*043036a2SApple OSS Distributions kIOSimpleLockAssertOwned = LCK_ASSERT_OWNED,
505*043036a2SApple OSS Distributions kIOSimpleLockAssertNotOwned = LCK_ASSERT_NOTOWNED
506*043036a2SApple OSS Distributions } IOSimpleLockAssertState;
507*043036a2SApple OSS Distributions
508*043036a2SApple OSS Distributions #ifdef IOLOCKS_INLINE
509*043036a2SApple OSS Distributions #define IOSimpleLockAssert(l, type) LCK_SPIN_ASSERT(l, type)
510*043036a2SApple OSS Distributions #else
511*043036a2SApple OSS Distributions /*! @function IOSimpleLockAssert
512*043036a2SApple OSS Distributions * @abstract Assert that spinlock is either held or not held by current thread.
513*043036a2SApple OSS Distributions * @discussion Call with either kIOSimpleLockAssertOwned or kIOSimpleLockAssertNotOwned.
514*043036a2SApple OSS Distributions * Panics the kernel if the lock is not owned if called with
515*043036a2SApple OSS Distributions * kIOSimpleLockAssertOwned and vice-versa.
516*043036a2SApple OSS Distributions */
517*043036a2SApple OSS Distributions void IOSimpleLockAssert(IOSimpleLock *lock, IOSimpleLockAssertState type);
518*043036a2SApple OSS Distributions #endif /* !IOLOCKS_INLINE */
519*043036a2SApple OSS Distributions #endif /* !XNU_KERNEL_PRIVATE */
520*043036a2SApple OSS Distributions
521*043036a2SApple OSS Distributions #if __LP64__
522*043036a2SApple OSS Distributions typedef boolean_t IOInterruptState;
523*043036a2SApple OSS Distributions #else
524*043036a2SApple OSS Distributions typedef long int IOInterruptState;
525*043036a2SApple OSS Distributions #endif
526*043036a2SApple OSS Distributions
527*043036a2SApple OSS Distributions /*! @function IOSimpleLockLockDisableInterrupt
528*043036a2SApple OSS Distributions * @abstract Lock a spin lock.
529*043036a2SApple OSS Distributions * @discussion Lock the spin lock. If the lock is held, spin waiting for its unlock. Simple locks disable preemption, cannot be held across any blocking operation, and should be held for very short periods. When used to synchronize between interrupt context and thread context they should be locked with interrupts disabled - IOSimpleLockLockDisableInterrupt() will do both. Locking the lock recursively from one thread will result in deadlock.
530*043036a2SApple OSS Distributions * @param lock Pointer to the lock. */
531*043036a2SApple OSS Distributions
532*043036a2SApple OSS Distributions static __inline__
533*043036a2SApple OSS Distributions IOInterruptState
IOSimpleLockLockDisableInterrupt(IOSimpleLock * lock)534*043036a2SApple OSS Distributions IOSimpleLockLockDisableInterrupt( IOSimpleLock * lock )
535*043036a2SApple OSS Distributions {
536*043036a2SApple OSS Distributions IOInterruptState state = ml_set_interrupts_enabled( false );
537*043036a2SApple OSS Distributions IOSimpleLockLock( lock );
538*043036a2SApple OSS Distributions return state;
539*043036a2SApple OSS Distributions }
540*043036a2SApple OSS Distributions
541*043036a2SApple OSS Distributions /*! @function IOSimpleLockUnlockEnableInterrupt
542*043036a2SApple OSS Distributions * @abstract Unlock a spin lock, and restore interrupt state.
543*043036a2SApple OSS Distributions * @discussion Unlock the lock, and restore preemption and interrupts to the state as they were when the lock was taken. Results are undefined if the caller has not locked the lock.
544*043036a2SApple OSS Distributions * @param lock Pointer to the lock.
545*043036a2SApple OSS Distributions * @param state The interrupt state returned by IOSimpleLockLockDisableInterrupt() */
546*043036a2SApple OSS Distributions
547*043036a2SApple OSS Distributions static __inline__
548*043036a2SApple OSS Distributions void
IOSimpleLockUnlockEnableInterrupt(IOSimpleLock * lock,IOInterruptState state)549*043036a2SApple OSS Distributions IOSimpleLockUnlockEnableInterrupt( IOSimpleLock * lock,
550*043036a2SApple OSS Distributions IOInterruptState state )
551*043036a2SApple OSS Distributions {
552*043036a2SApple OSS Distributions IOSimpleLockUnlock( lock );
553*043036a2SApple OSS Distributions ml_set_interrupts_enabled( state );
554*043036a2SApple OSS Distributions }
555*043036a2SApple OSS Distributions
556*043036a2SApple OSS Distributions #ifdef __cplusplus
557*043036a2SApple OSS Distributions } /* extern "C" */
558*043036a2SApple OSS Distributions #endif
559*043036a2SApple OSS Distributions
560*043036a2SApple OSS Distributions #endif /* !__IOKIT_IOLOCKS_H */
561