Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenspinlock.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ke/spinlock.c 00005 * PURPOSE: Spinlock and Queued Spinlock Support 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 #define LQ_WAIT 1 00016 #define LQ_OWN 2 00017 00018 /* PRIVATE FUNCTIONS *********************************************************/ 00019 00020 #if 0 00021 // 00022 // FIXME: The queued spinlock routines are broken. 00023 // 00024 00025 VOID 00026 FASTCALL 00027 KeAcquireQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK_QUEUE LockHandle) 00028 { 00029 #ifdef CONFIG_SMP 00030 PKSPIN_LOCK_QUEUE Prev; 00031 00032 /* Set the new lock */ 00033 Prev = (PKSPIN_LOCK_QUEUE) 00034 InterlockedExchange((PLONG)LockHandle->Next, 00035 (LONG)LockHandle); 00036 if (!Prev) 00037 { 00038 /* There was nothing there before. We now own it */ 00039 *LockHandle->Lock |= LQ_OWN; 00040 return; 00041 } 00042 00043 /* Set the wait flag */ 00044 *LockHandle->Lock |= LQ_WAIT; 00045 00046 /* Link us */ 00047 Prev->Next = (PKSPIN_LOCK_QUEUE)LockHandle; 00048 00049 /* Loop and wait */ 00050 while (*LockHandle->Lock & LQ_WAIT) 00051 YieldProcessor(); 00052 #endif 00053 } 00054 00055 VOID 00056 FASTCALL 00057 KeReleaseQueuedSpinLockFromDpcLevel(IN PKSPIN_LOCK_QUEUE LockHandle) 00058 { 00059 #ifdef CONFIG_SMP 00060 KSPIN_LOCK LockVal; 00061 PKSPIN_LOCK_QUEUE Waiter; 00062 00063 /* Remove own and wait flags */ 00064 *LockHandle->Lock &= ~(LQ_OWN | LQ_WAIT); 00065 LockVal = *LockHandle->Lock; 00066 00067 /* Check if we already own it */ 00068 if (LockVal == (KSPIN_LOCK)LockHandle) 00069 { 00070 /* Disown it */ 00071 LockVal = (KSPIN_LOCK) 00072 InterlockedCompareExchangePointer(LockHandle->Lock, 00073 NULL, 00074 LockHandle); 00075 } 00076 if (LockVal == (KSPIN_LOCK)LockHandle) return; 00077 00078 /* Need to wait for it */ 00079 Waiter = LockHandle->Next; 00080 while (!Waiter) 00081 { 00082 YieldProcessor(); 00083 Waiter = LockHandle->Next; 00084 } 00085 00086 /* It's gone */ 00087 *(ULONG_PTR*)&Waiter->Lock ^= (LQ_OWN | LQ_WAIT); 00088 LockHandle->Next = NULL; 00089 #endif 00090 } 00091 00092 #else 00093 // 00094 // HACK: Hacked to work like normal spinlocks 00095 // 00096 00097 VOID 00098 FASTCALL 00099 KeAcquireQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK_QUEUE LockHandle) 00100 { 00101 #ifdef CONFIG_SMP 00102 /* Make sure we are at DPC or above! */ 00103 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00104 { 00105 /* We aren't -- bugcheck */ 00106 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00107 (ULONG_PTR)LockHandle->Lock, 00108 KeGetCurrentIrql(), 00109 0, 00110 0); 00111 } 00112 00113 /* Do the inlined function */ 00114 KxAcquireSpinLock(LockHandle->Lock); 00115 #endif 00116 } 00117 00118 VOID 00119 FASTCALL 00120 KeReleaseQueuedSpinLockFromDpcLevel(IN PKSPIN_LOCK_QUEUE LockHandle) 00121 { 00122 #ifdef CONFIG_SMP 00123 /* Make sure we are at DPC or above! */ 00124 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00125 { 00126 /* We aren't -- bugcheck */ 00127 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00128 (ULONG_PTR)LockHandle->Lock, 00129 KeGetCurrentIrql(), 00130 0, 00131 0); 00132 } 00133 00134 /* Do the inlined function */ 00135 KxReleaseSpinLock(LockHandle->Lock); 00136 #endif 00137 } 00138 00139 #endif 00140 00141 /* PUBLIC FUNCTIONS **********************************************************/ 00142 00143 /* 00144 * @implemented 00145 */ 00146 KIRQL 00147 NTAPI 00148 KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt) 00149 { 00150 KIRQL OldIrql; 00151 00152 /* Raise IRQL */ 00153 KeRaiseIrql(Interrupt->SynchronizeIrql, &OldIrql); 00154 00155 /* Acquire spinlock on MP */ 00156 KeAcquireSpinLockAtDpcLevel(Interrupt->ActualLock); 00157 return OldIrql; 00158 } 00159 00160 /* 00161 * @implemented 00162 */ 00163 VOID 00164 NTAPI 00165 KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, 00166 IN KIRQL OldIrql) 00167 { 00168 /* Release lock on MP */ 00169 KeReleaseSpinLockFromDpcLevel(Interrupt->ActualLock); 00170 00171 /* Lower IRQL */ 00172 KeLowerIrql(OldIrql); 00173 } 00174 00175 /* 00176 * @implemented 00177 */ 00178 VOID 00179 NTAPI 00180 _KeInitializeSpinLock(IN PKSPIN_LOCK SpinLock) 00181 { 00182 /* Clear it */ 00183 *SpinLock = 0; 00184 } 00185 00186 /* 00187 * @implemented 00188 */ 00189 #undef KeAcquireSpinLockAtDpcLevel 00190 VOID 00191 NTAPI 00192 KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock) 00193 { 00194 /* Make sure we are at DPC or above! */ 00195 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00196 { 00197 /* We aren't -- bugcheck */ 00198 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00199 (ULONG_PTR)SpinLock, 00200 KeGetCurrentIrql(), 00201 0, 00202 0); 00203 } 00204 00205 /* Do the inlined function */ 00206 KxAcquireSpinLock(SpinLock); 00207 } 00208 00209 /* 00210 * @implemented 00211 */ 00212 #undef KeReleaseSpinLockFromDpcLevel 00213 VOID 00214 NTAPI 00215 KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock) 00216 { 00217 /* Make sure we are at DPC or above! */ 00218 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00219 { 00220 /* We aren't -- bugcheck */ 00221 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00222 (ULONG_PTR)SpinLock, 00223 KeGetCurrentIrql(), 00224 0, 00225 0); 00226 } 00227 00228 /* Do the inlined function */ 00229 KxReleaseSpinLock(SpinLock); 00230 } 00231 00232 /* 00233 * @implemented 00234 */ 00235 VOID 00236 FASTCALL 00237 KefAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock) 00238 { 00239 /* Make sure we are at DPC or above! */ 00240 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00241 { 00242 /* We aren't -- bugcheck */ 00243 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00244 (ULONG_PTR)SpinLock, 00245 KeGetCurrentIrql(), 00246 0, 00247 0); 00248 } 00249 00250 /* Do the inlined function */ 00251 KxAcquireSpinLock(SpinLock); 00252 } 00253 00254 /* 00255 * @implemented 00256 */ 00257 VOID 00258 FASTCALL 00259 KefReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock) 00260 { 00261 /* Make sure we are at DPC or above! */ 00262 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00263 { 00264 /* We aren't -- bugcheck */ 00265 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00266 (ULONG_PTR)SpinLock, 00267 KeGetCurrentIrql(), 00268 0, 00269 0); 00270 } 00271 00272 /* Do the inlined function */ 00273 KxReleaseSpinLock(SpinLock); 00274 } 00275 00276 /* 00277 * @implemented 00278 */ 00279 VOID 00280 FASTCALL 00281 KiAcquireSpinLock(IN PKSPIN_LOCK SpinLock) 00282 { 00283 /* Do the inlined function */ 00284 KxAcquireSpinLock(SpinLock); 00285 } 00286 00287 /* 00288 * @implemented 00289 */ 00290 VOID 00291 FASTCALL 00292 KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock) 00293 { 00294 /* Do the inlined function */ 00295 KxReleaseSpinLock(SpinLock); 00296 } 00297 00298 /* 00299 * @implemented 00300 */ 00301 BOOLEAN 00302 FASTCALL 00303 KeTryToAcquireSpinLockAtDpcLevel(IN OUT PKSPIN_LOCK SpinLock) 00304 { 00305 #ifdef CONFIG_SMP 00306 /* Check if it's already acquired */ 00307 if (!(*SpinLock)) 00308 { 00309 /* Try to acquire it */ 00310 if (InterlockedBitTestAndSet((PLONG)SpinLock, 0)) 00311 { 00312 /* Someone else acquired it */ 00313 return FALSE; 00314 } 00315 } 00316 else 00317 { 00318 /* It was already acquired */ 00319 return FALSE; 00320 } 00321 00322 #if DBG 00323 /* On debug builds, we OR in the KTHREAD */ 00324 *SpinLock = (ULONG_PTR)KeGetCurrentThread() | 1; 00325 #endif 00326 #endif 00327 00328 /* All is well, return TRUE */ 00329 return TRUE; 00330 } 00331 00332 /* 00333 * @implemented 00334 */ 00335 VOID 00336 FASTCALL 00337 KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock, 00338 IN PKLOCK_QUEUE_HANDLE LockHandle) 00339 { 00340 #ifdef CONFIG_SMP 00341 /* Set it up properly */ 00342 LockHandle->LockQueue.Next = NULL; 00343 LockHandle->LockQueue.Lock = SpinLock; 00344 #if 0 00345 KeAcquireQueuedSpinLockAtDpcLevel(LockHandle->LockQueue.Next); 00346 #else 00347 /* Make sure we are at DPC or above! */ 00348 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00349 { 00350 /* We aren't -- bugcheck */ 00351 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00352 (ULONG_PTR)LockHandle->LockQueue.Lock, 00353 KeGetCurrentIrql(), 00354 0, 00355 0); 00356 } 00357 00358 /* Acquire the lock */ 00359 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 00360 #endif 00361 #endif 00362 } 00363 00364 /* 00365 * @implemented 00366 */ 00367 VOID 00368 FASTCALL 00369 KeReleaseInStackQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle) 00370 { 00371 #ifdef CONFIG_SMP 00372 #if 0 00373 /* Call the internal function */ 00374 KeReleaseQueuedSpinLockFromDpcLevel(LockHandle->LockQueue.Next); 00375 #else 00376 /* Make sure we are at DPC or above! */ 00377 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 00378 { 00379 /* We aren't -- bugcheck */ 00380 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00381 (ULONG_PTR)LockHandle->LockQueue.Lock, 00382 KeGetCurrentIrql(), 00383 0, 00384 0); 00385 } 00386 00387 /* Release the lock */ 00388 KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK 00389 #endif 00390 #endif 00391 } 00392 00393 /* 00394 * @unimplemented 00395 */ 00396 KIRQL 00397 FASTCALL 00398 KeAcquireSpinLockForDpc(IN PKSPIN_LOCK SpinLock) 00399 { 00400 UNIMPLEMENTED; 00401 return 0; 00402 } 00403 00404 /* 00405 * @unimplemented 00406 */ 00407 VOID 00408 FASTCALL 00409 KeReleaseSpinLockForDpc(IN PKSPIN_LOCK SpinLock, 00410 IN KIRQL OldIrql) 00411 { 00412 UNIMPLEMENTED; 00413 } 00414 00415 /* 00416 * @unimplemented 00417 */ 00418 KIRQL 00419 FASTCALL 00420 KeAcquireInStackQueuedSpinLockForDpc(IN PKSPIN_LOCK SpinLock, 00421 IN PKLOCK_QUEUE_HANDLE LockHandle) 00422 { 00423 UNIMPLEMENTED; 00424 return 0; 00425 } 00426 00427 /* 00428 * @unimplemented 00429 */ 00430 VOID 00431 FASTCALL 00432 KeReleaseInStackQueuedSpinLockForDpc(IN PKLOCK_QUEUE_HANDLE LockHandle) 00433 { 00434 UNIMPLEMENTED; 00435 } 00436 00437 /* 00438 * @implemented 00439 */ 00440 BOOLEAN 00441 FASTCALL 00442 KeTestSpinLock(IN PKSPIN_LOCK SpinLock) 00443 { 00444 /* Test this spinlock */ 00445 if (*SpinLock) 00446 { 00447 /* Spinlock is busy, yield execution */ 00448 YieldProcessor(); 00449 00450 /* Return busy flag */ 00451 return FALSE; 00452 } 00453 00454 /* Spinlock appears to be free */ 00455 return TRUE; 00456 } 00457 00458 #ifdef _M_IX86 00459 VOID 00460 NTAPI 00461 Kii386SpinOnSpinLock(PKSPIN_LOCK SpinLock, ULONG Flags) 00462 { 00463 // FIXME: Handle flags 00464 UNREFERENCED_PARAMETER(Flags); 00465 00466 /* Spin until it's unlocked */ 00467 while (*(volatile KSPIN_LOCK *)SpinLock & 1) 00468 { 00469 // FIXME: Check for timeout 00470 00471 /* Yield and keep looping */ 00472 YieldProcessor(); 00473 } 00474 } 00475 #endif Generated on Thu May 24 2012 04:29:18 for ReactOS by
1.7.6.1
|