-/* $Id: spinlock.c,v 1.21 2004/06/23 22:31:51 ion Exp $
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/spinlock.c
* PURPOSE: Implements spinlocks
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- * 3/6/98: Created
- */
-
-/*
- * NOTE: On a uniprocessor machine spinlocks are implemented by raising
- * the irq level
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * David Welch (welch@cwcom.net)
*/
/* INCLUDES ****************************************************************/
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
#include <internal/debug.h>
+#undef KefAcquireSpinLockAtDpcLevel
+#undef KeAcquireSpinLockAtDpcLevel
+#undef KefReleaseSpinLockFromDpcLevel
+#undef KeReleaseSpinLockFromDpcLevel
+
/* FUNCTIONS ***************************************************************/
/*
* @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
* ARGUMENTS:
* Interrupt = Interrupt object to synchronize with
- * SynchronizeRoutine = Routine to call whose execution is
+ * SynchronizeRoutine = Routine to call whose execution is
* synchronized with the ISR
* SynchronizeContext = Parameter to pass to the synchronized routine
* RETURNS: TRUE if the operation succeeded
*/
+BOOLEAN
+STDCALL
+KeSynchronizeExecution(PKINTERRUPT Interrupt,
+ PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
+ PVOID SynchronizeContext)
{
- KIRQL oldlvl;
- BOOLEAN ret;
-
- KeRaiseIrql(Interrupt->SynchLevel, &oldlvl);
- KiAcquireSpinLock(Interrupt->IrqLock);
-
- ret = SynchronizeRoutine(SynchronizeContext);
-
- KiReleaseSpinLock(Interrupt->IrqLock);
- KeLowerIrql(oldlvl);
-
- return(ret);
+ KIRQL OldIrql;
+ BOOLEAN Status;
+
+ /* Raise IRQL and acquire lock on MP */
+ OldIrql = KeAcquireInterruptSpinLock(Interrupt);
+
+ /* Call the routine */
+ Status = SynchronizeRoutine(SynchronizeContext);
+
+ /* Release lock and lower IRQL */
+ KeReleaseInterruptSpinLock(Interrupt, OldIrql);
+
+ /* Return routine status */
+ return Status;
}
/*
- * @unimplemented
+ * @implemented
*/
-STDCALL
KIRQL
-KeAcquireInterruptSpinLock(
- IN PKINTERRUPT Interrupt
- )
+STDCALL
+KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
{
- UNIMPLEMENTED;
- return 0;
+ KIRQL OldIrql;
+
+ /* Raise IRQL */
+ KeRaiseIrql(Interrupt->SynchronizeIrql, &OldIrql);
+
+ /* Acquire spinlock on MP */
+ KiAcquireSpinLock(Interrupt->ActualLock);
+ return OldIrql;
}
/*
* @implemented
- */
-VOID STDCALL
-KeInitializeSpinLock (PKSPIN_LOCK SpinLock)
-/*
+ *
* FUNCTION: Initalizes a spinlock
* ARGUMENTS:
* SpinLock = Caller supplied storage for the spinlock
*/
+VOID
+STDCALL
+KeInitializeSpinLock(PKSPIN_LOCK SpinLock)
{
- *SpinLock = 0;
+ *SpinLock = 0;
}
-#undef KefAcquireSpinLockAtDpcLevel
-
/*
* @implemented
*/
-VOID FASTCALL
+VOID
+FASTCALL
KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
{
- assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
- KiAcquireSpinLock(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
+ *
+ * FUNCTION: Acquires a spinlock when the caller is already running at
* dispatch level
* ARGUMENTS:
* SpinLock = Spinlock to acquire
*/
+VOID
+STDCALL
+KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
{
- KefAcquireSpinLockAtDpcLevel(SpinLock);
+ KefAcquireSpinLockAtDpcLevel(SpinLock);
}
-
/*
- * @unimplemented
+ * @implemented
*/
VOID
FASTCALL
-KeAcquireInStackQueuedSpinLockAtDpcLevel(
- IN PKSPIN_LOCK SpinLock,
- IN PKLOCK_QUEUE_HANDLE LockHandle
- )
+KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
{
- UNIMPLEMENTED;
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ KiReleaseSpinLock(SpinLock);
}
-
-#undef KefReleaseSpinLockFromDpcLevel
-
/*
* @implemented
+ *
+ * FUNCTION: Releases a spinlock when the caller was running at dispatch
+ * level before acquiring it
+ * ARGUMENTS:
+ * SpinLock = Spinlock to release
*/
-VOID FASTCALL
-KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
+VOID
+STDCALL
+KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
{
- assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
- KiReleaseSpinLock(SpinLock);
+ KefReleaseSpinLockFromDpcLevel(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
- * ARGUMENTS:
- * SpinLock = Spinlock to release
- */
+VOID
+FASTCALL
+KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
{
- KefReleaseSpinLockFromDpcLevel(SpinLock);
+#ifdef CONFIG_SMP
+ for (;;)
+ {
+ /* Try to acquire it */
+ if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
+ {
+ /* Value changed... wait until it's locked */
+ while (*SpinLock == 1) YieldProcessor();
+ }
+ else
+ {
+ /* All is well, break out */
+ break;
+ }
+ }
+#endif /* CONFIG_SMP */
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
-FASTCALL
-KeReleaseInStackQueuedSpinLockFromDpcLevel(
- IN PKLOCK_QUEUE_HANDLE LockHandle
- )
+STDCALL
+KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt,
+ IN KIRQL OldIrql)
{
- UNIMPLEMENTED;
+ /* Release lock on MP */
+ KiReleaseSpinLock(Interrupt->ActualLock);
+
+ /* Lower IRQL */
+ KeLowerIrql(OldIrql);
}
/*
* @implemented
*/
-VOID FASTCALL
-KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
+VOID
+FASTCALL
+KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
{
- ULONG i;
-
- /*
- * FIXME: This depends on gcc assembling this test to a single load from
- * the spinlock's value.
- */
- if (*SpinLock >= 2)
- {
- DbgPrint("Lock %x has bad value %x\n", SpinLock, *SpinLock);
- KEBUGCHECK(0);
- }
-
- while ((i = InterlockedExchange((LONG *)SpinLock, 1)) == 1)
- {
-#ifndef MP
- DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
- KEBUGCHECK(0);
-#else /* not MP */
- /* Avoid reading the value again too fast */
-#endif /* MP */
- }
+#ifdef CONFIG_SMP
+ /* Simply clear it */
+ *SpinLock = 0;
+#endif
}
/*
* @unimplemented
*/
-STDCALL
VOID
-KeReleaseInterruptSpinLock(
- IN PKINTERRUPT Interrupt,
- IN KIRQL OldIrql
- )
+FASTCALL
+KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock,
+ IN PKLOCK_QUEUE_HANDLE LockHandle)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
}
/*
- * @implemented
+ * @unimplemented
*/
-VOID FASTCALL
-KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
+VOID
+FASTCALL
+KeReleaseInStackQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle)
{
- if (*SpinLock != 1)
- {
- DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
- KEBUGCHECK(0);
- }
- (void)InterlockedExchange((LONG *)SpinLock, 0);
+ UNIMPLEMENTED;
}
/* EOF */