[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / include / internal / spinlock.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/spinlock.h
5 * PURPOSE: Internal Inlined Functions for spinlocks, shared with HAL
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 VOID
10 NTAPI
11 Kii386SpinOnSpinLock(PKSPIN_LOCK SpinLock, ULONG Flags);
12
13 #ifndef CONFIG_SMP
14
15 //
16 // Spinlock Acquire at IRQL >= DISPATCH_LEVEL
17 //
18 FORCEINLINE
19 VOID
20 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
21 {
22 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
23 UNREFERENCED_PARAMETER(SpinLock);
24 }
25
26 //
27 // Spinlock Release at IRQL >= DISPATCH_LEVEL
28 //
29 FORCEINLINE
30 VOID
31 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
32 {
33 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
34 UNREFERENCED_PARAMETER(SpinLock);
35 }
36
37 #else
38
39 //
40 // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
41 //
42 FORCEINLINE
43 VOID
44 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
45 {
46 #ifdef DBG
47 /* Make sure that we don't own the lock already */
48 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) == *SpinLock)
49 {
50 /* We do, bugcheck! */
51 KeBugCheckEx(SPIN_LOCK_ALREADY_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
52 }
53 #endif
54
55 /* Try to acquire the lock */
56 while (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
57 {
58 #if defined(_M_IX86) && defined(DBG)
59 /* On x86 debug builds, we use a much slower but useful routine */
60 Kii386SpinOnSpinLock(SpinLock, 5);
61 #else
62 /* It's locked... spin until it's unlocked */
63 while (*(volatile KSPIN_LOCK *)SpinLock & 1)
64 {
65 /* Yield and keep looping */
66 YieldProcessor();
67 }
68 #endif
69 }
70 #ifdef DBG
71 /* On debug builds, we OR in the KTHREAD */
72 *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1;
73 #endif
74 }
75
76 //
77 // Spinlock Release at IRQL >= DISPATCH_LEVEL
78 //
79 FORCEINLINE
80 VOID
81 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
82 {
83 #if DBG
84 /* Make sure that the threads match */
85 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) != *SpinLock)
86 {
87 /* They don't, bugcheck */
88 KeBugCheckEx(SPIN_LOCK_NOT_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
89 }
90 #endif
91 /* Clear the lock */
92 InterlockedAnd((PLONG)SpinLock, 0);
93 }
94
95 #endif