]> git.saurik.com Git - apple/xnu.git/blob - iokit/IOKit/IOLocks.h
7771cff8c0b1dbd3d818886f46f059a48e5cc012
[apple/xnu.git] / iokit / IOKit / IOLocks.h
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 *
24 */
25
26 #ifndef __IOKIT_IOLOCKS_H
27 #define __IOKIT_IOLOCKS_H
28
29 #ifndef KERNEL
30 #error IOLocks.h is for kernel use only
31 #endif
32
33 #ifndef IOKIT_DEPRECATED
34 #define IOKIT_DEPRECATED 1
35 #endif
36
37 #include <IOKit/system.h>
38
39 #include <IOKit/IOReturn.h>
40 #include <IOKit/IOTypes.h>
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
46 #include <kern/lock.h>
47 #include <kern/simple_lock.h>
48 #include <machine/machine_routines.h>
49
50 /*
51 * Mutex lock operations
52 */
53
54 typedef mutex_t IOLock;
55
56 /*! @function IOLockAlloc
57 @abstract Allocates and initializes an osfmk mutex.
58 @discussion Allocates an osfmk mutex in general purpose memory, and initilizes it. Mutexes are general purpose blocking mutual exclusion locks, supplied by osfmk/kern/lock.h. This function may block and so should not be called from interrupt level or while a simple lock is held.
59 @result Pointer to the allocated lock, or zero on failure. */
60
61 IOLock * IOLockAlloc( void );
62
63 /*! @function IOLockFree
64 @abstract Frees an osfmk mutex.
65 @discussion Frees a lock allocated with IOLockAlloc. Any blocked waiters will not be woken.
66 @param lock Pointer to the allocated lock. */
67
68 void IOLockFree( IOLock * lock);
69
70 /*! @function IOLockLock
71 @abstract Lock an osfmk mutex.
72 @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 simple lock is held. Locking the mutex recursively from one thread will result in deadlock.
73 @param lock Pointer to the allocated lock. */
74
75 static __inline__
76 void IOLockLock( IOLock * lock)
77 {
78 _mutex_lock(lock);
79 }
80
81 /*! @function IOLockTryLock
82 @abstract Attempt to lock an osfmk mutex.
83 @discussion Lock the mutex if it is currently unlocked, and return true. If the lock is held by any thread, return false.
84 @param lock Pointer to the allocated lock.
85 @result True if the mutex was unlocked and is now locked by the caller, otherwise false. */
86
87 static __inline__
88 boolean_t IOLockTryLock( IOLock * lock)
89 {
90 return(_mutex_try(lock));
91 }
92
93 /*! @function IOLockUnlock
94 @abstract Unlock an osfmk mutex.
95 @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 simple lock is held.
96 @param lock Pointer to the allocated lock. */
97
98 static __inline__
99 void IOLockUnlock( IOLock * lock)
100 {
101 mutex_unlock(lock);
102 }
103
104 #if IOKIT_DEPRECATED
105
106 /* The following API is deprecated */
107
108 typedef enum {
109 kIOLockStateUnlocked = 0,
110 kIOLockStateLocked = 1,
111 } IOLockState;
112
113 void IOLockInitWithState( IOLock * lock, IOLockState state);
114 #define IOLockInit( l ) IOLockInitWithState( l, kIOLockStateUnlocked);
115
116 static __inline__ void IOTakeLock( IOLock * lock) { IOLockLock(lock); }
117 static __inline__ boolean_t IOTryLock( IOLock * lock) { return(IOLockTryLock(lock)); }
118 static __inline__ void IOUnlock( IOLock * lock) { IOLockUnlock(lock); }
119
120 #endif /* IOKIT_DEPRECATED */
121
122 /*
123 * Recursive lock operations
124 */
125
126 typedef struct _IORecursiveLock IORecursiveLock;
127
128 /*! @function IORecursiveLockAlloc
129 @abstract Allocates and initializes an recursive lock.
130 @discussion Allocates a recursive lock in general purpose memory, and initilizes it. Recursive locks function identically to osfmk mutexes but allow one thread to lock more than once, with balanced unlocks.
131 @result Pointer to the allocated lock, or zero on failure. */
132
133 IORecursiveLock * IORecursiveLockAlloc( void );
134
135 /*! @function IORecursiveLockFree
136 @abstract Frees a recursive lock.
137 @discussion Frees a lock allocated with IORecursiveLockAlloc. Any blocked waiters will not be woken.
138 @param lock Pointer to the allocated lock. */
139
140 void IORecursiveLockFree( IORecursiveLock * lock);
141
142 /*! @function IORecursiveLockLock
143 @abstract Lock a recursive lock.
144 @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 simple lock is held. The lock may be taken recursively by the same thread, with a balanced number of calls to IORecursiveLockUnlock.
145 @param lock Pointer to the allocated lock. */
146
147 void IORecursiveLockLock( IORecursiveLock * lock);
148
149 /*! @function IORecursiveLockTryLock
150 @abstract Attempt to lock a recursive lock.
151 @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.
152 @param lock Pointer to the allocated lock.
153 @result True if the lock is now locked by the caller, otherwise false. */
154
155 boolean_t IORecursiveLockTryLock( IORecursiveLock * lock);
156
157 /*! @function IORecursiveLockUnlock
158 @abstract Unlock a recursive lock.
159 @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 simple lock is held.
160 @param lock Pointer to the allocated lock. */
161
162 void IORecursiveLockUnlock( IORecursiveLock * lock);
163
164 /*! @function IORecursiveLockHaveLock
165 @abstract Check if a recursive lock is held by the calling thread.
166 @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.
167 @param lock Pointer to the allocated lock.
168 @result True if the calling thread holds the lock otherwise false. */
169
170 boolean_t IORecursiveLockHaveLock( const IORecursiveLock * lock);
171
172 extern int IORecursiveLockSleep( IORecursiveLock *_lock,
173 void *event, UInt32 interType);
174 extern void IORecursiveLockWakeup( IORecursiveLock *_lock,
175 void *event, bool oneThread);
176
177 /*
178 * Complex (read/write) lock operations
179 */
180
181 typedef lock_t IORWLock;
182
183 /*! @function IORWLockAlloc
184 @abstract Allocates and initializes an osfmk general (read/write) lock.
185 @discussion Allocates an initializes an osfmk lock_t in general purpose memory, and initilizes it. Read/write locks provide for multiple readers, one exclusive writer, and are supplied by osfmk/kern/lock.h. This function may block and so should not be called from interrupt level or while a simple lock is held.
186 @result Pointer to the allocated lock, or zero on failure. */
187
188 IORWLock * IORWLockAlloc( void );
189
190 /*! @function IORWLockFree
191 @abstract Frees an osfmk general (read/write) lock.
192 @discussion Frees a lock allocated with IORWLockAlloc. Any blocked waiters will not be woken.
193 @param lock Pointer to the allocated lock. */
194
195 void IORWLockFree( IORWLock * lock);
196
197 /*! @function IORWLockRead
198 @abstract Lock an osfmk lock for read.
199 @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 simple lock is held. Locking the lock recursively from one thread, for read or write, can result in deadlock.
200 @param lock Pointer to the allocated lock. */
201
202 static __inline__
203 void IORWLockRead( IORWLock * lock)
204 {
205 lock_read( lock);
206 }
207
208 /*! @function IORWLockWrite
209 @abstract Lock an osfmk lock for write.
210 @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 simple lock is held. Locking the lock recursively from one thread, for read or write, can result in deadlock.
211 @param lock Pointer to the allocated lock. */
212
213 static __inline__
214 void IORWLockWrite( IORWLock * lock)
215 {
216 lock_write( lock);
217 }
218
219 /*! @function IORWLockUnlock
220 @abstract Unlock an osfmk lock.
221 @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 simple lock is held.
222 @param lock Pointer to the allocated lock. */
223
224 static __inline__
225 void IORWLockUnlock( IORWLock * lock)
226 {
227 lock_done( lock);
228 }
229
230 #if IOKIT_DEPRECATED
231
232 /* The following API is deprecated */
233
234 static __inline__ void IOReadLock( IORWLock * lock) { IORWLockRead(lock); }
235 static __inline__ void IOWriteLock( IORWLock * lock) { IORWLockWrite(lock); }
236 static __inline__ void IORWUnlock( IORWLock * lock) { IORWLockUnlock(lock); }
237
238 #endif /* IOKIT_DEPRECATED */
239
240
241 /*
242 * Simple locks. Cannot block while holding a simple lock.
243 */
244
245 typedef simple_lock_data_t IOSimpleLock;
246
247 /*! @function IOSimpleLockAlloc
248 @abstract Allocates and initializes an osfmk simple (spin) lock.
249 @discussion Allocates an initializes an osfmk simple lock in general purpose memory, and initilizes it. Simple locks provide non-blocking mutual exclusion for synchronization between thread context and interrupt context, or for multiprocessor synchronization, and are supplied by osfmk/kern/simple_lock.h. This function may block and so should not be called from interrupt level or while a simple lock is held.
250 @result Pointer to the allocated lock, or zero on failure. */
251
252 IOSimpleLock * IOSimpleLockAlloc( void );
253
254 /*! @function IOSimpleLockFree
255 @abstract Frees an osfmk simple (spin) lock.
256 @discussion Frees a lock allocated with IOSimpleLockAlloc.
257 @param lock Pointer to the lock. */
258
259 void IOSimpleLockFree( IOSimpleLock * lock );
260
261 /*! @function IOSimpleLockInit
262 @abstract Initialize an osfmk simple (spin) lock.
263 @discussion Initialize an embedded osfmk simple lock, to the unlocked state.
264 @param lock Pointer to the lock. */
265
266 void IOSimpleLockInit( IOSimpleLock * lock );
267
268 /*! @function IOSimpleLockLock
269 @abstract Lock an osfmk simple lock.
270 @discussion Lock the simple 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.
271 @param lock Pointer to the lock. */
272
273 static __inline__
274 void IOSimpleLockLock( IOSimpleLock * lock )
275 {
276 simple_lock( lock );
277 }
278
279 /*! @function IOSimpleLockTryLock
280 @abstract Attempt to lock an osfmk simple lock.
281 @discussion Lock the simple 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.
282 @param lock Pointer to the lock.
283 @result True if the lock was unlocked and is now locked by the caller, otherwise false. */
284
285 static __inline__
286 boolean_t IOSimpleLockTryLock( IOSimpleLock * lock )
287 {
288 return( simple_lock_try( lock ) );
289 }
290
291 /*! @function IOSimpleLockUnlock
292 @abstract Unlock an osfmk simple lock.
293 @discussion Unlock the lock, and restore preemption. Results are undefined if the caller has not locked the lock.
294 @param lock Pointer to the lock. */
295
296 static __inline__
297 void IOSimpleLockUnlock( IOSimpleLock * lock )
298 {
299 simple_unlock( lock );
300 }
301
302 typedef long int IOInterruptState;
303
304 /*! @function IOSimpleLockLockDisableInterrupt
305 @abstract Lock an osfmk simple lock.
306 @discussion Lock the simple 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.
307 @param lock Pointer to the lock. */
308
309 static __inline__
310 IOInterruptState IOSimpleLockLockDisableInterrupt( IOSimpleLock * lock )
311 {
312 IOInterruptState state = ml_set_interrupts_enabled( false );
313 simple_lock( lock );
314 return( state );
315 }
316
317 /*! @function IOSimpleLockUnlockEnableInterrupt
318 @abstract Unlock an osfmk simple lock, and restore interrupt state.
319 @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.
320 @param lock Pointer to the lock.
321 @param state The interrupt state returned by IOSimpleLockLockDisableInterrupt() */
322
323 static __inline__
324 void IOSimpleLockUnlockEnableInterrupt( IOSimpleLock * lock,
325 IOInterruptState state )
326 {
327 simple_unlock( lock );
328 ml_set_interrupts_enabled( state );
329 }
330
331 #ifdef __cplusplus
332 } /* extern "C" */
333 #endif
334
335 #endif /* !__IOKIT_IOLOCKS_H */
336