1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/spinlock.c
5 * PURPOSE: Spinlock and Queued Spinlock Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 /* This file is compiled twice. Once for UP and once for MP */
12
13 #include <hal.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 #include <internal/spinlock.h>
18
19 #undef KeAcquireSpinLock
20 #undef KeReleaseSpinLock
21
22 /* GLOBALS *******************************************************************/
23
24 ULONG_PTR HalpSystemHardwareFlags;
25 KSPIN_LOCK HalpSystemHardwareLock;
26
27 /* FUNCTIONS *****************************************************************/
28
29 #ifdef _M_IX86
30
31 #ifdef _MINIHAL_
32 VOID
33 FASTCALL
KefAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)34 KefAcquireSpinLockAtDpcLevel(
35 IN PKSPIN_LOCK SpinLock)
36 {
37 #if DBG
38 /* To be on par with HAL/NTOSKRNL */
39 *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1;
40 #endif
41 }
42 #endif /* defined(_MINIHAL_) */
43
44 /*
45 * @implemented
46 */
47 KIRQL
48 FASTCALL
KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)49 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)
50 {
51 KIRQL OldIrql;
52
53 /* Raise to sync */
54 KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
55
56 /* Acquire the lock and return */
57 KxAcquireSpinLock(SpinLock);
58 return OldIrql;
59 }
60
61 /*
62 * @implemented
63 */
64 KIRQL
65 FASTCALL
KfAcquireSpinLock(PKSPIN_LOCK SpinLock)66 KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
67 {
68 KIRQL OldIrql;
69
70 /* Raise to dispatch and acquire the lock */
71 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
72 KxAcquireSpinLock(SpinLock);
73 return OldIrql;
74 }
75
76 /*
77 * @implemented
78 */
79 VOID
80 FASTCALL
KfReleaseSpinLock(PKSPIN_LOCK SpinLock,KIRQL OldIrql)81 KfReleaseSpinLock(PKSPIN_LOCK SpinLock,
82 KIRQL OldIrql)
83 {
84 /* Release the lock and lower IRQL back */
85 KxReleaseSpinLock(SpinLock);
86 KeLowerIrql(OldIrql);
87 }
88
89 /*
90 * @implemented
91 */
92 KIRQL
93 FASTCALL
KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)94 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
95 {
96 KIRQL OldIrql;
97
98 /* Raise to dispatch */
99 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
100
101 /* Acquire the lock */
102 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
103 return OldIrql;
104 }
105
106 /*
107 * @implemented
108 */
109 KIRQL
110 FASTCALL
KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)111 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
112 {
113 KIRQL OldIrql;
114
115 /* Raise to synch */
116 KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
117
118 /* Acquire the lock */
119 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
120 return OldIrql;
121 }
122
123 /*
124 * @implemented
125 */
126 VOID
127 FASTCALL
KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,IN PKLOCK_QUEUE_HANDLE LockHandle)128 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,
129 IN PKLOCK_QUEUE_HANDLE LockHandle)
130 {
131 /* Set up the lock */
132 LockHandle->LockQueue.Next = NULL;
133 LockHandle->LockQueue.Lock = SpinLock;
134
135 /* Raise to dispatch */
136 KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql);
137
138 /* Acquire the lock */
139 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
140 }
141
142 /*
143 * @implemented
144 */
145 VOID
146 FASTCALL
KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock,IN PKLOCK_QUEUE_HANDLE LockHandle)147 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock,
148 IN PKLOCK_QUEUE_HANDLE LockHandle)
149 {
150 /* Set up the lock */
151 LockHandle->LockQueue.Next = NULL;
152 LockHandle->LockQueue.Lock = SpinLock;
153
154 /* Raise to synch */
155 KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql);
156
157 /* Acquire the lock */
158 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
159 }
160
161 /*
162 * @implemented
163 */
164 VOID
165 FASTCALL
KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,IN KIRQL OldIrql)166 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
167 IN KIRQL OldIrql)
168 {
169 /* Release the lock */
170 KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
171
172 /* Lower IRQL back */
173 KeLowerIrql(OldIrql);
174 }
175
176 /*
177 * @implemented
178 */
179 VOID
180 FASTCALL
KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)181 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
182 {
183 /* Simply lower IRQL back */
184 KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK
185 KeLowerIrql(LockHandle->OldIrql);
186 }
187
188 #ifndef _MINIHAL_
189 /*
190 * @implemented
191 */
192 BOOLEAN
193 FASTCALL
KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,IN PKIRQL OldIrql)194 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
195 IN PKIRQL OldIrql)
196 {
197 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock;
198
199 /* KM tests demonstrate that this raises IRQL even if locking fails */
200 KeRaiseIrql(SYNCH_LEVEL, OldIrql);
201 /* HACK */
202 return KeTryToAcquireSpinLockAtDpcLevel(Lock);
203 }
204
205 /*
206 * @implemented
207 */
208 LOGICAL
209 FASTCALL
KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,OUT PKIRQL OldIrql)210 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
211 OUT PKIRQL OldIrql)
212 {
213 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock;
214
215 /* KM tests demonstrate that this raises IRQL even if locking fails */
216 KeRaiseIrql(DISPATCH_LEVEL, OldIrql);
217 /* HACK */
218 return KeTryToAcquireSpinLockAtDpcLevel(Lock);
219 }
220 #endif /* !defined(_MINIHAL_) */
221
222 #endif /* defined(_M_IX86) */
223
224 VOID
225 NTAPI
HalpAcquireCmosSpinLock(VOID)226 HalpAcquireCmosSpinLock(VOID)
227 {
228 ULONG_PTR Flags;
229
230 /* Get flags and disable interrupts */
231 Flags = __readeflags();
232 _disable();
233
234 /* Acquire the lock */
235 KxAcquireSpinLock(&HalpSystemHardwareLock);
236
237 /* We have the lock, save the flags now */
238 HalpSystemHardwareFlags = Flags;
239 }
240
241 VOID
242 NTAPI
HalpReleaseCmosSpinLock(VOID)243 HalpReleaseCmosSpinLock(VOID)
244 {
245 ULONG_PTR Flags;
246
247 /* Get the flags */
248 Flags = HalpSystemHardwareFlags;
249
250 /* Release the lock */
251 KxReleaseSpinLock(&HalpSystemHardwareLock);
252
253 /* Restore the flags */
254 __writeeflags(Flags);
255 }
256
257