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