ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

spinlock.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.