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 KeRaiseIrql(Interrupt
->SynchLevel
, &oldIrql
);
67 KiAcquireSpinLock(Interrupt
->ActualLock
);
75 KeInitializeSpinLock (PKSPIN_LOCK SpinLock
)
77 * FUNCTION: Initalizes a spinlock
79 * SpinLock = Caller supplied storage for the spinlock
85 #undef KefAcquireSpinLockAtDpcLevel
91 KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock
)
93 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
94 KiAcquireSpinLock(SpinLock
);
97 #undef KeAcquireSpinLockAtDpcLevel
103 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock
)
105 * FUNCTION: Acquires a spinlock when the caller is already running at
108 * SpinLock = Spinlock to acquire
111 KefAcquireSpinLockAtDpcLevel(SpinLock
);
120 KeAcquireInStackQueuedSpinLockAtDpcLevel(
121 IN PKSPIN_LOCK SpinLock
,
122 IN PKLOCK_QUEUE_HANDLE LockHandle
129 #undef KefReleaseSpinLockFromDpcLevel
135 KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock
)
137 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
138 KiReleaseSpinLock(SpinLock
);
141 #undef KeReleaseSpinLockFromDpcLevel
147 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock
)
149 * FUNCTION: Releases a spinlock when the caller was running at dispatch
150 * level before acquiring it
152 * SpinLock = Spinlock to release
155 KefReleaseSpinLockFromDpcLevel(SpinLock
);
163 KeReleaseInStackQueuedSpinLockFromDpcLevel(
164 IN PKLOCK_QUEUE_HANDLE LockHandle
174 KiAcquireSpinLock(PKSPIN_LOCK SpinLock
)
179 * FIXME: This depends on gcc assembling this test to a single load from
180 * the spinlock's value.
182 ASSERT(*SpinLock
< 2);
184 while ((i
= InterlockedExchangeUL(SpinLock
, 1)) == 1)
187 /* Avoid reading the value again too fast */
189 __asm__
__volatile__ ("1:\n\t"
195 while (0 != *(volatile KSPIN_LOCK
*)SpinLock
);
198 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock
, i
);
199 KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED
, (ULONG
)SpinLock
, 0, 0, 0);
200 #endif /* CONFIG_SMP */
209 KeReleaseInterruptSpinLock(
210 IN PKINTERRUPT Interrupt
,
214 KiReleaseSpinLock(Interrupt
->ActualLock
);
215 KeLowerIrql(OldIrql
);
222 KiReleaseSpinLock(PKSPIN_LOCK SpinLock
)
226 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock
);
227 KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED
, (ULONG
)SpinLock
, 0, 0, 0);
229 (void)InterlockedExchangeUL(SpinLock
, 0);