xref: /reactos/hal/halx86/generic/spinlock.c (revision 09dde2cf)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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