Make sure compiler doesn't optimize our wait loop away. Patch by Thomas Weidenmueller
[reactos.git] / reactos / ntoskrnl / ke / spinlock.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ke/spinlock.c
5 * PURPOSE: Implements spinlocks
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * David Welch (welch@cwcom.net)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 #undef KefAcquireSpinLockAtDpcLevel
17 #undef KeAcquireSpinLockAtDpcLevel
18 #undef KefReleaseSpinLockFromDpcLevel
19 #undef KeReleaseSpinLockFromDpcLevel
20
21 /* FUNCTIONS ***************************************************************/
22
23 /*
24 * @implemented
25 *
26 * FUNCTION: Synchronizes the execution of a given routine with the ISR
27 * of a given interrupt object
28 * ARGUMENTS:
29 * Interrupt = Interrupt object to synchronize with
30 * SynchronizeRoutine = Routine to call whose execution is
31 * synchronized with the ISR
32 * SynchronizeContext = Parameter to pass to the synchronized routine
33 * RETURNS: TRUE if the operation succeeded
34 */
35 BOOLEAN
36 STDCALL
37 KeSynchronizeExecution(PKINTERRUPT Interrupt,
38 PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
39 PVOID SynchronizeContext)
40 {
41 KIRQL OldIrql;
42 BOOLEAN Status;
43
44 /* Raise IRQL and acquire lock on MP */
45 OldIrql = KeAcquireInterruptSpinLock(Interrupt);
46
47 /* Call the routine */
48 Status = SynchronizeRoutine(SynchronizeContext);
49
50 /* Release lock and lower IRQL */
51 KeReleaseInterruptSpinLock(Interrupt, OldIrql);
52
53 /* Return routine status */
54 return Status;
55 }
56
57 /*
58 * @implemented
59 */
60 KIRQL
61 STDCALL
62 KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
63 {
64 KIRQL OldIrql;
65
66 /* Raise IRQL */
67 KeRaiseIrql(Interrupt->SynchronizeIrql, &OldIrql);
68
69 /* Acquire spinlock on MP */
70 KiAcquireSpinLock(Interrupt->ActualLock);
71 return OldIrql;
72 }
73
74 /*
75 * @implemented
76 *
77 * FUNCTION: Initalizes a spinlock
78 * ARGUMENTS:
79 * SpinLock = Caller supplied storage for the spinlock
80 */
81 VOID
82 STDCALL
83 KeInitializeSpinLock(PKSPIN_LOCK SpinLock)
84 {
85 *SpinLock = 0;
86 }
87
88 /*
89 * @implemented
90 */
91 VOID
92 FASTCALL
93 KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
94 {
95 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
96 KiAcquireSpinLock(SpinLock);
97 }
98
99 /*
100 * @implemented
101 *
102 * FUNCTION: Acquires a spinlock when the caller is already running at
103 * dispatch level
104 * ARGUMENTS:
105 * SpinLock = Spinlock to acquire
106 */
107 VOID
108 STDCALL
109 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
110 {
111 KefAcquireSpinLockAtDpcLevel(SpinLock);
112 }
113
114 /*
115 * @implemented
116 */
117 VOID
118 FASTCALL
119 KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
120 {
121 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
122 KiReleaseSpinLock(SpinLock);
123 }
124
125 /*
126 * @implemented
127 *
128 * FUNCTION: Releases a spinlock when the caller was running at dispatch
129 * level before acquiring it
130 * ARGUMENTS:
131 * SpinLock = Spinlock to release
132 */
133 VOID
134 STDCALL
135 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
136 {
137 KefReleaseSpinLockFromDpcLevel(SpinLock);
138 }
139
140 /*
141 * @implemented
142 */
143 VOID
144 FASTCALL
145 KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
146 {
147 #ifdef CONFIG_SMP
148 for (;;)
149 {
150 /* Try to acquire it */
151 if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
152 {
153 /* Value changed... wait until it's locked */
154 while (*(volatile KSPIN_LOCK *)SpinLock == 1) YieldProcessor();
155 }
156 else
157 {
158 /* All is well, break out */
159 break;
160 }
161 }
162 #endif /* CONFIG_SMP */
163 }
164
165 /*
166 * @implemented
167 */
168 VOID
169 STDCALL
170 KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt,
171 IN KIRQL OldIrql)
172 {
173 /* Release lock on MP */
174 KiReleaseSpinLock(Interrupt->ActualLock);
175
176 /* Lower IRQL */
177 KeLowerIrql(OldIrql);
178 }
179
180 /*
181 * @implemented
182 */
183 VOID
184 FASTCALL
185 KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
186 {
187 #ifdef CONFIG_SMP
188 /* Simply clear it */
189 *SpinLock = 0;
190 #endif
191 }
192
193 /*
194 * @unimplemented
195 */
196 VOID
197 FASTCALL
198 KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock,
199 IN PKLOCK_QUEUE_HANDLE LockHandle)
200 {
201 UNIMPLEMENTED;
202 }
203
204 /*
205 * @unimplemented
206 */
207 VOID
208 FASTCALL
209 KeReleaseInStackQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle)
210 {
211 UNIMPLEMENTED;
212 }
213
214 /* EOF */