- 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@cwcom.net) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * David Welch (welch@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)