- Fix InterlockedBitTestAndReset and InterlockedBitTestAndSet
- Implement YieldProcessor
- Fix formatting in spinlock.c
- KiAcquireSpinlock and KiReleaseSpinLock should be no-op functions on
uniprocessor machines.
- KiReleaseSpinLock does not need interlocked access to release the
lock.
- Use portable code for KiAcquireSpinLock. Also use interlocked bit
operations since they are faster.
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
Modified: trunk/reactos/w32api/include/winnt.h
_____
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
--- trunk/reactos/ntoskrnl/ke/spinlock.c 2005-12-29 19:12:09 UTC
(rev 20435)
+++ trunk/reactos/ntoskrnl/ke/spinlock.c 2005-12-29 19:54:42 UTC
(rev 20436)
@@ -1,34 +1,28 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/spinlock.c
* PURPOSE: Implements spinlocks
- *
- * PROGRAMMERS: David Welch (welch(a)cwcom.net)
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ * David Welch (welch(a)cwcom.net)
*/
-/*
- * NOTE: On a uniprocessor machine spinlocks are implemented by raising
- * the irq level
- */
-
/* INCLUDES
****************************************************************/
#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:
@@ -38,17 +32,26 @@
* 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;
+ KIRQL OldIrql;
+ BOOLEAN Status;
- oldlvl = KeAcquireInterruptSpinLock(Interrupt);
+ /* Raise IRQL and acquire lock on MP */
+ OldIrql = KeAcquireInterruptSpinLock(Interrupt);
- ret = SynchronizeRoutine(SynchronizeContext);
+ /* Call the routine */
+ Status = SynchronizeRoutine(SynchronizeContext);
- KeReleaseInterruptSpinLock(Interrupt, oldlvl);
+ /* Release lock and lower IRQL */
+ KeReleaseInterruptSpinLock(Interrupt, OldIrql);
- return(ret);
+ /* Return routine status */
+ return Status;
}
/*
@@ -56,176 +59,156 @@
*/
KIRQL
STDCALL
-KeAcquireInterruptSpinLock(
- IN PKINTERRUPT Interrupt
- )
+KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
{
- KIRQL oldIrql;
+ KIRQL OldIrql;
- KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql);
- KiAcquireSpinLock(Interrupt->ActualLock);
- return 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
* dispatch level
* ARGUMENTS:
* SpinLock = Spinlock to acquire
*/
-{
- KefAcquireSpinLockAtDpcLevel(SpinLock);
-}
-
-
-/*
- * @unimplemented
- */
VOID
-FASTCALL
-KeAcquireInStackQueuedSpinLockAtDpcLevel(
- IN PKSPIN_LOCK SpinLock,
- IN PKLOCK_QUEUE_HANDLE LockHandle
- )
+STDCALL
+KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
{
- UNIMPLEMENTED;
+ KefAcquireSpinLockAtDpcLevel(SpinLock);
}
-
-#undef KefReleaseSpinLockFromDpcLevel
-
/*
* @implemented
*/
-VOID FASTCALL
+VOID
+FASTCALL
KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
{
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- KiReleaseSpinLock(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
* ARGUMENTS:
* SpinLock = Spinlock to release
*/
+VOID
+STDCALL
+KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
{
- KefReleaseSpinLockFromDpcLevel(SpinLock);
+ KefReleaseSpinLockFromDpcLevel(SpinLock);
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
FASTCALL
-KeReleaseInStackQueuedSpinLockFromDpcLevel(
- IN PKLOCK_QUEUE_HANDLE LockHandle
- )
+KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
{
- UNIMPLEMENTED;
+#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 */
}
/*
* @implemented
*/
-VOID FASTCALL
-KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
+VOID
+STDCALL
+KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt,
+ IN KIRQL OldIrql)
{
- ULONG i;
+ /* Release lock on MP */
+ KiReleaseSpinLock(Interrupt->ActualLock);
- /*
- * FIXME: This depends on gcc assembling this test to a single load
from
- * the spinlock's value.
- */
- ASSERT(*SpinLock < 2);
+ /* Lower IRQL */
+ KeLowerIrql(OldIrql);
+}
- while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
- {
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
+{
#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);
+ /* Simply clear it */
+ *SpinLock = 0;
#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
+ * @unimplemented
*/
VOID
-STDCALL
-KeReleaseInterruptSpinLock(
- IN PKINTERRUPT Interrupt,
- IN KIRQL OldIrql
- )
+FASTCALL
+KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock,
+ IN PKLOCK_QUEUE_HANDLE
LockHandle)
{
- KiReleaseSpinLock(Interrupt->ActualLock);
- KeLowerIrql(OldIrql);
+ 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);
- KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED, (ULONG)SpinLock, 0, 0, 0);
- }
- (void)InterlockedExchangeUL(SpinLock, 0);
+ UNIMPLEMENTED;
}
/* EOF */
_____
Modified: trunk/reactos/w32api/include/winnt.h
--- trunk/reactos/w32api/include/winnt.h 2005-12-29 19:12:09 UTC
(rev 20435)
+++ trunk/reactos/w32api/include/winnt.h 2005-12-29 19:54:42 UTC
(rev 20436)
@@ -3700,7 +3700,7 @@
{
LONG OldBit;
- __asm__ __volatile__("lock"
+ __asm__ __volatile__("lock "
"btsl %2,%1\n\t"
"sbbl %0,%0\n\t"
:"=r" (OldBit),"=m" (*Base)
@@ -3715,7 +3715,7 @@
{
LONG OldBit;
- __asm__ __volatile__("lock"
+ __asm__ __volatile__("lock "
"btrl %2,%1\n\t"
"sbbl %0,%0\n\t"
:"=r" (OldBit),"=m" (*Base)
@@ -3726,6 +3726,8 @@
#endif
+#define YieldProcessor() __asm__ __volatile__("pause");
+
#if defined(_AMD64_)
#if defined(_M_AMD64)