xref: /reactos/hal/halx86/generic/spinlock.c (revision 40462c92)
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 /*
176  * @implemented
177  */
178 BOOLEAN
179 FASTCALL
180 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
181                                          IN PKIRQL OldIrql)
182 {
183 #ifdef CONFIG_SMP
184     ERROR_DBGBREAK("FIXME: Unused\n"); // FIXME: Unused
185     return FALSE;
186 #endif
187 
188     /* Simply raise to synch */
189     KeRaiseIrql(SYNCH_LEVEL, OldIrql);
190 
191     /* Add an explicit memory barrier to prevent the compiler from reordering
192        memory accesses across the borders of spinlocks */
193     KeMemoryBarrierWithoutFence();
194 
195     /* Always return true on UP Machines */
196     return TRUE;
197 }
198 
199 /*
200  * @implemented
201  */
202 LOGICAL
203 FASTCALL
204 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
205                              OUT PKIRQL OldIrql)
206 {
207 #ifdef CONFIG_SMP
208     ERROR_DBGBREAK("FIXME: Unused\n"); // FIXME: Unused
209     return FALSE;
210 #endif
211 
212     /* Simply raise to dispatch */
213     KeRaiseIrql(DISPATCH_LEVEL, OldIrql);
214 
215     /* Add an explicit memory barrier to prevent the compiler from reordering
216        memory accesses across the borders of spinlocks */
217     KeMemoryBarrierWithoutFence();
218 
219     /* Always return true on UP Machines */
220     return TRUE;
221 }
222 
223 #endif
224 
225 VOID
226 NTAPI
227 HalpAcquireCmosSpinLock(VOID)
228 {
229     ULONG_PTR Flags;
230 
231     /* Get flags and disable interrupts */
232     Flags = __readeflags();
233     _disable();
234 
235     /* Acquire the lock */
236     KxAcquireSpinLock(&HalpSystemHardwareLock);
237 
238     /* We have the lock, save the flags now */
239     HalpSystemHardwareFlags = Flags;
240 }
241 
242 VOID
243 NTAPI
244 HalpReleaseCmosSpinLock(VOID)
245 {
246     ULONG_PTR Flags;
247 
248     /* Get the flags */
249     Flags = HalpSystemHardwareFlags;
250 
251     /* Release the lock */
252     KxReleaseSpinLock(&HalpSystemHardwareLock);
253 
254     /* Restore the flags */
255     __writeeflags(Flags);
256 }
257 
258