From 3785fc8f828f1ef0070dbf0bcb6d788d1a7bf203 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 29 Dec 2005 19:54:42 +0000 Subject: [PATCH] - 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. svn path=/trunk/; revision=20436 --- reactos/ntoskrnl/ke/spinlock.c | 219 +++++++++++++++------------------ reactos/w32api/include/winnt.h | 6 +- 2 files changed, 105 insertions(+), 120 deletions(-) diff --git a/reactos/ntoskrnl/ke/spinlock.c b/reactos/ntoskrnl/ke/spinlock.c index 59d249229a1..a4f969d85a8 100644 --- a/reactos/ntoskrnl/ke/spinlock.c +++ b/reactos/ntoskrnl/ke/spinlock.c @@ -1,16 +1,10 @@ -/* $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) - */ - -/* - * 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 ****************************************************************/ @@ -19,16 +13,16 @@ #define NDEBUG #include +#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 @@ KeSynchronizeExecution (PKINTERRUPT Interrupt, * 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 @@ KeSynchronizeExecution (PKINTERRUPT Interrupt, */ 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 */ diff --git a/reactos/w32api/include/winnt.h b/reactos/w32api/include/winnt.h index fb511421d28..eb9022769db 100644 --- a/reactos/w32api/include/winnt.h +++ b/reactos/w32api/include/winnt.h @@ -3700,7 +3700,7 @@ InterlockedBitTestAndSet(IN LONG *Base, { 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 @@ InterlockedBitTestAndReset(IN LONG *Base, { 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 @@ InterlockedBitTestAndReset(IN LONG *Base, #endif +#define YieldProcessor() __asm__ __volatile__("pause"); + #if defined(_AMD64_) #if defined(_M_AMD64) -- 2.17.1