xref: /xnu-12377.81.4/iokit/IOKit/IOLocks.h (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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