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
->SynchronizeIrql
, &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.
181 ASSERT(*SpinLock
< 2);
183 while ((i
= InterlockedExchangeUL(SpinLock
, 1)) == 1)
186 /* Avoid reading the value again too fast */
188 __asm__
__volatile__ ("1:\n\t"
194 while (0 != *(volatile KSPIN_LOCK
*)SpinLock
);
197 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock
, i
);
198 KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED
, (ULONG
)SpinLock
, 0, 0, 0);
199 #endif /* CONFIG_SMP */
208 KeReleaseInterruptSpinLock(
209 IN PKINTERRUPT Interrupt
,
213 KiReleaseSpinLock(Interrupt
->ActualLock
);
214 KeLowerIrql(OldIrql
);
221 KiReleaseSpinLock(PKSPIN_LOCK SpinLock
)
225 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock
);
226 KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED
, (ULONG
)SpinLock
, 0, 0, 0);
228 (void)InterlockedExchangeUL(SpinLock
, 0);