KD System Rewrite:
[reactos.git] / reactos / ntoskrnl / ke / spinlock.c
index 71fa7b9..258a15d 100644 (file)
@@ -1,12 +1,11 @@
-/* $Id: spinlock.c,v 1.4 2000/06/09 20:07:20 ekohl Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/spinlock.c
  * PURPOSE:         Implements spinlocks
- * PROGRAMMER:      David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *                  3/6/98: Created
+ * 
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /*
 
 /* INCLUDES ****************************************************************/
 
-#include <ddk/ntddk.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
 #include <internal/debug.h>
 
 /* FUNCTIONS ***************************************************************/
 
-BOOLEAN
-STDCALL
-KeSynchronizeExecution (
-       PKINTERRUPT             Interrupt,
-       PKSYNCHRONIZE_ROUTINE   SynchronizeRoutine,
-       PVOID                   SynchronizeContext
-       )
+/*
+ * @implemented
+ */
+BOOLEAN STDCALL
+KeSynchronizeExecution (PKINTERRUPT            Interrupt,
+                       PKSYNCHRONIZE_ROUTINE   SynchronizeRoutine,
+                       PVOID                   SynchronizeContext)
 /*
  * FUNCTION: Synchronizes the execution of a given routine with the ISR
  * of a given interrupt object
@@ -43,36 +42,64 @@ KeSynchronizeExecution (
    KIRQL oldlvl;
    BOOLEAN ret;
    
-   KeRaiseIrql(Interrupt->SynchLevel,&oldlvl);
-   KeAcquireSpinLockAtDpcLevel(Interrupt->IrqLock);
+   oldlvl = KeAcquireInterruptSpinLock(Interrupt);
    
    ret = SynchronizeRoutine(SynchronizeContext);
    
-   KeReleaseSpinLockFromDpcLevel(Interrupt->IrqLock);
-   KeLowerIrql(oldlvl);
+   KeReleaseInterruptSpinLock(Interrupt, oldlvl);
    
    return(ret);
 }
 
-VOID
+/*
+ * @implemented
+ */
+KIRQL
 STDCALL
-KeInitializeSpinLock (
-       PKSPIN_LOCK     SpinLock
-       )
+KeAcquireInterruptSpinLock(
+    IN PKINTERRUPT Interrupt
+    )
+{
+   KIRQL oldIrql;
+        
+   KeRaiseIrql(Interrupt->SynchLevel, &oldIrql);
+   KiAcquireSpinLock(Interrupt->ActualLock);
+   return oldIrql;
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+KeInitializeSpinLock (PKSPIN_LOCK      SpinLock)
 /*
  * FUNCTION: Initalizes a spinlock
  * ARGUMENTS:
  *           SpinLock = Caller supplied storage for the spinlock
  */
 {
-   SpinLock->Lock = 0;
+   *SpinLock = 0;
 }
 
-VOID
-STDCALL
-KeAcquireSpinLockAtDpcLevel (
-       PKSPIN_LOCK     SpinLock
-       )
+#undef KefAcquireSpinLockAtDpcLevel
+
+/*
+ * @implemented
+ */
+VOID FASTCALL
+KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
+{
+  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+  KiAcquireSpinLock(SpinLock);
+}
+
+#undef KeAcquireSpinLockAtDpcLevel
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK       SpinLock)
 /*
  * FUNCTION: Acquires a spinlock when the caller is already running at 
  * dispatch level
@@ -80,20 +107,43 @@ KeAcquireSpinLockAtDpcLevel (
  *        SpinLock = Spinlock to acquire
  */
 {
-   ULONG i;
-   
-   while ((i = InterlockedExchange(&SpinLock->Lock, 1)) == 1)
-     {
-       DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
-       KeBugCheck(0);
-     }
+  KefAcquireSpinLockAtDpcLevel(SpinLock);
 }
 
+
+/*
+ * @unimplemented
+ */
 VOID
-STDCALL
-KeReleaseSpinLockFromDpcLevel (
-       PKSPIN_LOCK     SpinLock
-       )
+FASTCALL
+KeAcquireInStackQueuedSpinLockAtDpcLevel(
+    IN PKSPIN_LOCK SpinLock,
+    IN PKLOCK_QUEUE_HANDLE LockHandle
+    )
+{
+       UNIMPLEMENTED;
+}
+
+
+#undef KefReleaseSpinLockFromDpcLevel
+
+/*
+ * @implemented
+ */
+VOID FASTCALL
+KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
+{
+  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+  KiReleaseSpinLock(SpinLock);  
+}
+
+#undef KeReleaseSpinLockFromDpcLevel
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK     SpinLock)
 /*
  * FUNCTION: Releases a spinlock when the caller was running at dispatch
  * level before acquiring it
@@ -101,12 +151,81 @@ KeReleaseSpinLockFromDpcLevel (
  *         SpinLock = Spinlock to release
  */
 {
-   if (SpinLock->Lock != 1)
-     {
-       DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
-       KeBugCheck(0);
-     }
-   (void)InterlockedExchange(&SpinLock->Lock, 0);
+  KefReleaseSpinLockFromDpcLevel(SpinLock);
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+FASTCALL
+KeReleaseInStackQueuedSpinLockFromDpcLevel(
+    IN PKLOCK_QUEUE_HANDLE LockHandle
+    )
+{
+       UNIMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+VOID FASTCALL
+KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
+{
+  ULONG i;
+
+  /*
+   * FIXME: This depends on gcc assembling this test to a single load from
+   * the spinlock's value.
+   */
+  ASSERT(*SpinLock < 2);
+   
+  while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
+  {
+#ifdef CONFIG_SMP
+    /* Avoid reading the value again too fast */
+#if 1
+    __asm__ __volatile__ ("1:\n\t"
+                         "cmpl $0,(%0)\n\t"
+                         "jne  1b\n\t"
+                         :
+                          : "r" (SpinLock));
+#else                    
+    while (0 != *(volatile KSPIN_LOCK*)SpinLock);
+#endif
+#else
+    DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
+    KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED, (ULONG)SpinLock, 0, 0, 0);
+#endif /* CONFIG_SMP */
+  }
+}
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+KeReleaseInterruptSpinLock(
+       IN PKINTERRUPT Interrupt,
+       IN KIRQL OldIrql
+       )
+{
+   KiReleaseSpinLock(Interrupt->ActualLock);
+   KeLowerIrql(OldIrql);
+}
+
+/*
+ * @implemented
+ */
+VOID FASTCALL
+KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
+{
+  if (*SpinLock != 1)
+  {
+    DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
+    KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED, (ULONG)SpinLock, 0, 0, 0);
+  }
+  (void)InterlockedExchangeUL(SpinLock, 0);
 }
 
 /* EOF */