[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/internal/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 /* Add an explicit memory barrier to prevent the compiler from reordering
26 memory accesses across the borders of spinlocks */
27 KeMemoryBarrierWithoutFence();
28 }
29
30 //
31 // Spinlock Release at IRQL >= DISPATCH_LEVEL
32 //
33 FORCEINLINE
34 VOID
35 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
36 {
37 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
38 UNREFERENCED_PARAMETER(SpinLock);
39
40 /* Add an explicit memory barrier to prevent the compiler from reordering
41 memory accesses across the borders of spinlocks */
42 KeMemoryBarrierWithoutFence();
43 }
44
45 #else
46
47 //
48 // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
49 //
50 FORCEINLINE
51 VOID
52 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
53 {
54 #if DBG
55 /* Make sure that we don't own the lock already */
56 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) == *SpinLock)
57 {
58 /* We do, bugcheck! */
59 KeBugCheckEx(SPIN_LOCK_ALREADY_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
60 }
61 #endif
62
63 /* Try to acquire the lock */
64 while (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
65 {
66 #if defined(_M_IX86) && DBG
67 /* On x86 debug builds, we use a much slower but useful routine */
68 Kii386SpinOnSpinLock(SpinLock, 5);
69 #else
70 /* It's locked... spin until it's unlocked */
71 while (*(volatile KSPIN_LOCK *)SpinLock & 1)
72 {
73 /* Yield and keep looping */
74 YieldProcessor();
75 }
76 #endif
77 }
78 #if DBG
79 /* On debug builds, we OR in the KTHREAD */
80 *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1;
81 #endif
82 }
83
84 //
85 // Spinlock Release at IRQL >= DISPATCH_LEVEL
86 //
87 FORCEINLINE
88 VOID
89 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
90 {
91 #if DBG
92 /* Make sure that the threads match */
93 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) != *SpinLock)
94 {
95 /* They don't, bugcheck */
96 KeBugCheckEx(SPIN_LOCK_NOT_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
97 }
98 #endif
99 /* Clear the lock */
100 InterlockedAnd((PLONG)SpinLock, 0);
101 }
102
103 #endif