3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/up/spinlock.c
5 * PURPOSE: Spinlock and Queued Spinlock Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
11 /* Enable this (and the define in irq.S) to make UP HAL work for MP Kernel */
12 /* #define CONFIG_SMP */
18 #undef KeAcquireSpinLock
19 #undef KeReleaseSpinLock
22 // This is duplicated from ke_x.h
26 // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
30 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock
)
32 /* Make sure that we don't own the lock already */
33 if (((KSPIN_LOCK
)KeGetCurrentThread() | 1) == *SpinLock
)
35 /* We do, bugcheck! */
36 KeBugCheckEx(SPIN_LOCK_ALREADY_OWNED
, (ULONG_PTR
)SpinLock
, 0, 0, 0);
41 /* Try to acquire it */
42 if (InterlockedBitTestAndSet((PLONG
)SpinLock
, 0))
44 /* Value changed... wait until it's locked */
45 while (*(volatile KSPIN_LOCK
*)SpinLock
== 1)
48 /* On debug builds, we use a much slower but useful routine */
49 //Kii386SpinOnSpinLock(SpinLock, 5);
51 /* FIXME: Do normal yield for now */
54 /* Otherwise, just yield and keep looping */
62 /* On debug builds, we OR in the KTHREAD */
63 *SpinLock
= (KSPIN_LOCK
)KeGetCurrentThread() | 1;
65 /* All is well, break out */
72 // Spinlock Release at IRQL >= DISPATCH_LEVEL
76 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock
)
79 /* Make sure that the threads match */
80 if (((KSPIN_LOCK
)KeGetCurrentThread() | 1) != *SpinLock
)
82 /* They don't, bugcheck */
83 KeBugCheckEx(SPIN_LOCK_NOT_OWNED
, (ULONG_PTR
)SpinLock
, 0, 0, 0);
87 InterlockedAnd((PLONG
)SpinLock
, 0);
93 // Spinlock Acquire at IRQL >= DISPATCH_LEVEL
97 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock
)
99 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
100 UNREFERENCED_PARAMETER(SpinLock
);
104 // Spinlock Release at IRQL >= DISPATCH_LEVEL
108 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock
)
110 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
111 UNREFERENCED_PARAMETER(SpinLock
);
116 /* FUNCTIONS *****************************************************************/
123 KeAcquireSpinLock(PKSPIN_LOCK SpinLock
,
126 /* Call the fastcall function */
127 *OldIrql
= KfAcquireSpinLock(SpinLock
);
135 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock
)
140 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
142 /* Acquire the lock and return */
143 KxAcquireSpinLock(SpinLock
);
152 KeReleaseSpinLock(PKSPIN_LOCK SpinLock
,
155 /* Call the fastcall function */
156 KfReleaseSpinLock(SpinLock
, NewIrql
);
164 KfAcquireSpinLock(PKSPIN_LOCK SpinLock
)
168 /* Raise to dispatch and acquire the lock */
169 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
170 KxAcquireSpinLock(SpinLock
);
179 KfReleaseSpinLock(PKSPIN_LOCK SpinLock
,
182 /* Release the lock and lower IRQL back */
183 KxReleaseSpinLock(SpinLock
);
184 KeLowerIrql(OldIrql
);
192 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber
)
196 /* Raise to dispatch */
197 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
199 /* Acquire the lock */
200 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue
[LockNumber
].Lock
); // HACK
209 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber
)
214 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
216 /* Acquire the lock */
217 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue
[LockNumber
].Lock
); // HACK
226 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock
,
227 IN PKLOCK_QUEUE_HANDLE LockHandle
)
229 /* Set up the lock */
230 LockHandle
->LockQueue
.Next
= NULL
;
231 LockHandle
->LockQueue
.Lock
= SpinLock
;
233 /* Raise to dispatch */
234 KeRaiseIrql(DISPATCH_LEVEL
, &LockHandle
->OldIrql
);
236 /* Acquire the lock */
237 KxAcquireSpinLock(LockHandle
->LockQueue
.Lock
); // HACK
245 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock
,
246 IN PKLOCK_QUEUE_HANDLE LockHandle
)
248 /* Set up the lock */
249 LockHandle
->LockQueue
.Next
= NULL
;
250 LockHandle
->LockQueue
.Lock
= SpinLock
;
253 KeRaiseIrql(SYNCH_LEVEL
, &LockHandle
->OldIrql
);
255 /* Acquire the lock */
256 KxAcquireSpinLock(LockHandle
->LockQueue
.Lock
); // HACK
264 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber
,
267 /* Release the lock */
268 KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue
[LockNumber
].Lock
); // HACK
270 /* Lower IRQL back */
271 KeLowerIrql(OldIrql
);
279 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle
)
281 /* Simply lower IRQL back */
282 KxReleaseSpinLock(LockHandle
->LockQueue
.Lock
); // HACK
283 KeLowerIrql(LockHandle
->OldIrql
);
291 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber
,
295 ASSERT(FALSE
); // FIXME: Unused
299 /* Simply raise to synch */
300 KeRaiseIrql(SYNCH_LEVEL
, OldIrql
);
302 /* Always return true on UP Machines */
311 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber
,
315 ASSERT(FALSE
); // FIXME: Unused
319 /* Simply raise to dispatch */
320 KeRaiseIrql(DISPATCH_LEVEL
, OldIrql
);
322 /* Always return true on UP Machines */
332 KeRaiseIrql(KIRQL NewIrql
,
335 /* Call the fastcall function */
336 *OldIrql
= KfRaiseIrql(NewIrql
);
345 KeLowerIrql(KIRQL NewIrql
)
347 /* Call the fastcall function */
348 KfLowerIrql(NewIrql
);