xref: /xnu-11215/iokit/Kernel/IOLocks.cpp (revision 368ad365)
1 /*
2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
7  *
8  * This file contains Original Code and/or Modifications of Original Code
9  * as defined in and that are subject to the Apple Public Source License
10  * Version 2.0 (the 'License'). You may not use this file except in
11  * compliance with the License. Please obtain a copy of the License at
12  * http://www.opensource.apple.com/apsl/ and read it before using this
13  * file.
14  *
15  * The Original Code and all software distributed under the License are
16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20  * Please see the License for the specific language governing rights and
21  * limitations under the License.
22  *
23  * @APPLE_LICENSE_HEADER_END@
24  */
25 /*
26  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
27  *
28  * HISTORY
29  *
30  */
31 
32 
33 #include <IOKit/system.h>
34 
35 #include <IOKit/IOReturn.h>
36 #include <IOKit/IOLib.h>
37 #include <IOKit/assert.h>
38 
39 extern "C" {
40 #include <kern/simple_lock.h>
41 #include <machine/machine_routines.h>
42 
43 IOLock * IOLockAlloc( void )
44 {
45     return( mutex_alloc(ETAP_IO_AHA) );
46 }
47 
48 void	IOLockFree( IOLock * lock)
49 {
50     mutex_free( lock );
51 }
52 
53 void	IOLockInitWithState( IOLock * lock, IOLockState state)
54 {
55     if( state == kIOLockStateLocked)
56         IOLockLock( lock);
57 }
58 
59 struct _IORecursiveLock {
60     mutex_t  *	mutex;
61     thread_t	thread;
62     UInt32	count;
63 };
64 
65 IORecursiveLock * IORecursiveLockAlloc( void )
66 {
67     _IORecursiveLock * lock;
68 
69     lock = IONew( _IORecursiveLock, 1);
70     if( !lock)
71         return( 0 );
72 
73     lock->mutex = mutex_alloc(ETAP_IO_AHA);
74     if( lock->mutex) {
75         lock->thread = 0;
76         lock->count  = 0;
77     } else {
78         IODelete( lock, _IORecursiveLock, 1);
79         lock = 0;
80     }
81 
82     return( (IORecursiveLock *) lock );
83 }
84 
85 void IORecursiveLockFree( IORecursiveLock * _lock )
86 {
87     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
88 
89     mutex_free( lock->mutex );
90     IODelete( lock, _IORecursiveLock, 1);
91 }
92 
93 void IORecursiveLockLock( IORecursiveLock * _lock)
94 {
95     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
96 
97     if( lock->thread == IOThreadSelf())
98         lock->count++;
99     else {
100         mutex_lock( lock->mutex );
101         assert( lock->thread == 0 );
102         assert( lock->count == 0 );
103         lock->thread = IOThreadSelf();
104         lock->count = 1;
105     }
106 }
107 
108 boolean_t IORecursiveLockTryLock( IORecursiveLock * _lock)
109 {
110     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
111 
112     if( lock->thread == IOThreadSelf()) {
113         lock->count++;
114 	return( true );
115     } else {
116         if( mutex_try( lock->mutex )) {
117             assert( lock->thread == 0 );
118             assert( lock->count == 0 );
119             lock->thread = IOThreadSelf();
120             lock->count = 1;
121             return( true );
122 	}
123     }
124     return( false );
125 }
126 
127 void IORecursiveLockUnlock( IORecursiveLock * _lock)
128 {
129     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
130 
131     assert( lock->thread == IOThreadSelf() );
132 
133     if( 0 == (--lock->count)) {
134         lock->thread = 0;
135         mutex_unlock( lock->mutex );
136     }
137 }
138 
139 boolean_t IORecursiveLockHaveLock( const IORecursiveLock * _lock)
140 {
141     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
142 
143     return( lock->thread == IOThreadSelf());
144 }
145 
146 int IORecursiveLockSleep(IORecursiveLock *_lock, void *event, UInt32 interType)
147 {
148     _IORecursiveLock * lock = (_IORecursiveLock *)_lock;
149     UInt32 count = lock->count;
150     int res;
151 
152     assert(lock->thread == IOThreadSelf());
153     assert(lock->count == 1 || interType == THREAD_UNINT);
154 
155     lock->count = 0;
156     lock->thread = 0;
157     res = thread_sleep_mutex((event_t) event, lock->mutex, (int) interType);
158 
159     // Must re-establish the recursive lock no matter why we woke up
160     // otherwise we would potentially leave the return path corrupted.
161     assert(lock->thread == 0);
162     assert(lock->count == 0);
163     lock->thread = IOThreadSelf();
164     lock->count = count;
165     return res;
166 }
167 
168 void IORecursiveLockWakeup(IORecursiveLock *, void *event, bool oneThread)
169 {
170     thread_wakeup_prim((event_t) event, oneThread, THREAD_AWAKENED);
171 }
172 
173 /*
174  * Complex (read/write) lock operations
175  */
176 
177 IORWLock * IORWLockAlloc( void )
178 {
179     IORWLock * lock;
180 
181     lock = lock_alloc( true, ETAP_IO_AHA, ETAP_IO_AHA);
182 
183     return( lock);
184 }
185 
186 void	IORWLockFree( IORWLock * lock)
187 {
188     lock_free( lock );
189 }
190 
191 
192 /*
193  * Spin locks
194  */
195 
196 IOSimpleLock * IOSimpleLockAlloc( void )
197 {
198     IOSimpleLock *	lock;
199 
200     lock = (IOSimpleLock *) IOMalloc( sizeof(IOSimpleLock));
201     if( lock)
202 	IOSimpleLockInit( lock );
203 
204     return( lock );
205 }
206 
207 void IOSimpleLockInit( IOSimpleLock * lock)
208 {
209     simple_lock_init( (simple_lock_t) lock, ETAP_IO_AHA );
210 }
211 
212 void IOSimpleLockFree( IOSimpleLock * lock )
213 {
214     IOFree( lock, sizeof(IOSimpleLock));
215 }
216 
217 } /* extern "C" */
218 
219 
220