3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/spinlock.c
6 * PURPOSE: Implements spinlocks
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
12 * NOTE: On a uniprocessor machine spinlocks are implemented by raising
16 /* INCLUDES ****************************************************************/
20 #include <internal/debug.h>
22 /* FUNCTIONS ***************************************************************/
28 KeSynchronizeExecution (PKINTERRUPT Interrupt
,
29 PKSYNCHRONIZE_ROUTINE SynchronizeRoutine
,
30 PVOID SynchronizeContext
)
32 * FUNCTION: Synchronizes the execution of a given routine with the ISR
33 * of a given interrupt object
35 * Interrupt = Interrupt object to synchronize with
36 * SynchronizeRoutine = Routine to call whose execution is
37 * synchronized with the ISR
38 * SynchronizeContext = Parameter to pass to the synchronized routine
39 * RETURNS: TRUE if the operation succeeded
45 oldlvl
= KeAcquireInterruptSpinLock(Interrupt
);
47 ret
= SynchronizeRoutine(SynchronizeContext
);
49 KeReleaseInterruptSpinLock(Interrupt
, oldlvl
);
59 KeAcquireInterruptSpinLock(
60 IN PKINTERRUPT Interrupt
65 KeRaiseIrql(Interrupt
->SynchLevel
, &oldIrql
);
66 KiAcquireSpinLock(Interrupt
->ActualLock
);
74 KeInitializeSpinLock (PKSPIN_LOCK SpinLock
)
76 * FUNCTION: Initalizes a spinlock
78 * SpinLock = Caller supplied storage for the spinlock
84 #undef KefAcquireSpinLockAtDpcLevel
90 KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock
)
92 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
93 KiAcquireSpinLock(SpinLock
);
96 #undef KeAcquireSpinLockAtDpcLevel
102 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock
)
104 * FUNCTION: Acquires a spinlock when the caller is already running at
107 * SpinLock = Spinlock to acquire
110 KefAcquireSpinLockAtDpcLevel(SpinLock
);
119 KeAcquireInStackQueuedSpinLockAtDpcLevel(
120 IN PKSPIN_LOCK SpinLock
,
121 IN PKLOCK_QUEUE_HANDLE LockHandle
128 #undef KefReleaseSpinLockFromDpcLevel
134 KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock
)
136 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
137 KiReleaseSpinLock(SpinLock
);
140 #undef KeReleaseSpinLockFromDpcLevel
146 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock
)
148 * FUNCTION: Releases a spinlock when the caller was running at dispatch
149 * level before acquiring it
151 * SpinLock = Spinlock to release
154 KefReleaseSpinLockFromDpcLevel(SpinLock
);
162 KeReleaseInStackQueuedSpinLockFromDpcLevel(
163 IN PKLOCK_QUEUE_HANDLE LockHandle
173 KiAcquireSpinLock(PKSPIN_LOCK SpinLock
)
178 * FIXME: This depends on gcc assembling this test to a single load from
179 * the spinlock's value.
183 DbgPrint("Lock %x has bad value %x\n", SpinLock
, *SpinLock
);
187 while ((i
= InterlockedExchangeUL(SpinLock
, 1)) == 1)
190 /* Avoid reading the value again too fast */
192 __asm__
__volatile__ ("1:\n\t"
198 while (0 != *(volatile KSPIN_LOCK
*)SpinLock
);
201 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock
, i
);
203 #endif /* CONFIG_SMP */
212 KeReleaseInterruptSpinLock(
213 IN PKINTERRUPT Interrupt
,
217 KiReleaseSpinLock(Interrupt
->ActualLock
);
218 KeLowerIrql(OldIrql
);
225 KiReleaseSpinLock(PKSPIN_LOCK SpinLock
)
229 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock
);
232 (void)InterlockedExchangeUL(SpinLock
, 0);