Reactos
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
24ULONG_PTR HalpSystemHardwareFlags;
25KSPIN_LOCK HalpSystemHardwareLock;
26
27/* FUNCTIONS *****************************************************************/
28
29#ifdef _M_IX86
30
31#ifdef _MINIHAL_
32VOID
33FASTCALL
34KefAcquireSpinLockAtDpcLevel(
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 */
47KIRQL
48FASTCALL
49KeAcquireSpinLockRaiseToSynch(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 */
64KIRQL
65FASTCALL
66KfAcquireSpinLock(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 */
79VOID
80FASTCALL
81KfReleaseSpinLock(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 */
92KIRQL
93FASTCALL
94KeAcquireQueuedSpinLock(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 */
109KIRQL
110FASTCALL
111KeAcquireQueuedSpinLockRaiseToSynch(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 */
126VOID
127FASTCALL
128KeAcquireInStackQueuedSpinLock(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 */
145VOID
146FASTCALL
147KeAcquireInStackQueuedSpinLockRaiseToSynch(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 */
164VOID
165FASTCALL
166KeReleaseQueuedSpinLock(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 */
179VOID
180FASTCALL
181KeReleaseInStackQueuedSpinLock(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 */
192BOOLEAN
193FASTCALL
194KeTryToAcquireQueuedSpinLockRaiseToSynch(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 */
208LOGICAL
209FASTCALL
210KeTryToAcquireQueuedSpinLock(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
224VOID
225NTAPI
226HalpAcquireCmosSpinLock(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
241VOID
242NTAPI
243HalpReleaseCmosSpinLock(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