xref: /reactos/hal/halx86/generic/spinlock.c (revision bbabe248)
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 /*
32  * @implemented
33  */
34 KIRQL
35 FASTCALL
36 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)
37 {
38     KIRQL OldIrql;
39 
40     /* Raise to sync */
41     KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
42 
43     /* Acquire the lock and return */
44     KxAcquireSpinLock(SpinLock);
45     return OldIrql;
46 }
47 
48 /*
49  * @implemented
50  */
51 KIRQL
52 FASTCALL
53 KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
54 {
55     KIRQL OldIrql;
56 
57     /* Raise to dispatch and acquire the lock */
58     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
59     KxAcquireSpinLock(SpinLock);
60     return OldIrql;
61 }
62 
63 /*
64  * @implemented
65  */
66 VOID
67 FASTCALL
68 KfReleaseSpinLock(PKSPIN_LOCK SpinLock,
69                   KIRQL OldIrql)
70 {
71     /* Release the lock and lower IRQL back */
72     KxReleaseSpinLock(SpinLock);
73     KeLowerIrql(OldIrql);
74 }
75 
76 /*
77  * @implemented
78  */
79 KIRQL
80 FASTCALL
81 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
82 {
83     KIRQL OldIrql;
84 
85     /* Raise to dispatch */
86     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
87 
88     /* Acquire the lock */
89     KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
90     return OldIrql;
91 }
92 
93 /*
94  * @implemented
95  */
96 KIRQL
97 FASTCALL
98 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
99 {
100     KIRQL OldIrql;
101 
102     /* Raise to synch */
103     KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
104 
105     /* Acquire the lock */
106     KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
107     return OldIrql;
108 }
109 
110 /*
111  * @implemented
112  */
113 VOID
114 FASTCALL
115 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,
116                                IN PKLOCK_QUEUE_HANDLE LockHandle)
117 {
118     /* Set up the lock */
119     LockHandle->LockQueue.Next = NULL;
120     LockHandle->LockQueue.Lock = SpinLock;
121 
122     /* Raise to dispatch */
123     KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql);
124 
125     /* Acquire the lock */
126     KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
127 }
128 
129 /*
130  * @implemented
131  */
132 VOID
133 FASTCALL
134 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock,
135                                            IN PKLOCK_QUEUE_HANDLE LockHandle)
136 {
137     /* Set up the lock */
138     LockHandle->LockQueue.Next = NULL;
139     LockHandle->LockQueue.Lock = SpinLock;
140 
141     /* Raise to synch */
142     KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql);
143 
144     /* Acquire the lock */
145     KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
146 }
147 
148 /*
149  * @implemented
150  */
151 VOID
152 FASTCALL
153 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
154                         IN KIRQL OldIrql)
155 {
156     /* Release the lock */
157     KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
158 
159     /* Lower IRQL back */
160     KeLowerIrql(OldIrql);
161 }
162 
163 /*
164  * @implemented
165  */
166 VOID
167 FASTCALL
168 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
169 {
170     /* Simply lower IRQL back */
171     KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK
172     KeLowerIrql(LockHandle->OldIrql);
173 }
174 
175 #ifndef _MINIHAL_
176 /*
177  * @implemented
178  */
179 BOOLEAN
180 FASTCALL
181 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
182                                          IN PKIRQL OldIrql)
183 {
184     PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock;
185 
186     /* KM tests demonstrate that this raises IRQL even if locking fails */
187     KeRaiseIrql(SYNCH_LEVEL, OldIrql);
188     /* HACK */
189     return KeTryToAcquireSpinLockAtDpcLevel(Lock);
190 }
191 
192 /*
193  * @implemented
194  */
195 LOGICAL
196 FASTCALL
197 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
198                              OUT PKIRQL OldIrql)
199 {
200     PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock;
201 
202     /* KM tests demonstrate that this raises IRQL even if locking fails */
203     KeRaiseIrql(DISPATCH_LEVEL, OldIrql);
204     /* HACK */
205     return KeTryToAcquireSpinLockAtDpcLevel(Lock);
206 }
207 #endif /* !defined(_MINIHAL_) */
208 #endif /* defined(_M_IX86) */
209 
210 VOID
211 NTAPI
212 HalpAcquireCmosSpinLock(VOID)
213 {
214     ULONG_PTR Flags;
215 
216     /* Get flags and disable interrupts */
217     Flags = __readeflags();
218     _disable();
219 
220     /* Acquire the lock */
221     KxAcquireSpinLock(&HalpSystemHardwareLock);
222 
223     /* We have the lock, save the flags now */
224     HalpSystemHardwareFlags = Flags;
225 }
226 
227 VOID
228 NTAPI
229 HalpReleaseCmosSpinLock(VOID)
230 {
231     ULONG_PTR Flags;
232 
233     /* Get the flags */
234     Flags = HalpSystemHardwareFlags;
235 
236     /* Release the lock */
237     KxReleaseSpinLock(&HalpSystemHardwareLock);
238 
239     /* Restore the flags */
240     __writeeflags(Flags);
241 }
242 
243