-/* $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
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
* 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
* 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 */