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