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