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