xref: /reactos/ntoskrnl/ke/amd64/spinlock.c (revision 2ed56fa7)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS HAL
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            ntoskrnl/ke/amd64/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 #include <ntoskrnl.h>
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck 
15c2c66affSColin Finck #undef KeAcquireSpinLock
16c2c66affSColin Finck #undef KeReleaseSpinLock
17c2c66affSColin Finck 
18c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
19c2c66affSColin Finck 
20c2c66affSColin Finck /*
21c2c66affSColin Finck  * @implemented
22c2c66affSColin Finck  */
23c2c66affSColin Finck KIRQL
KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)24c2c66affSColin Finck KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)
25c2c66affSColin Finck {
26c2c66affSColin Finck     KIRQL OldIrql;
27c2c66affSColin Finck 
28c2c66affSColin Finck     /* Raise to sync */
29c2c66affSColin Finck     KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
30c2c66affSColin Finck 
31c2c66affSColin Finck     /* Acquire the lock and return */
32c2c66affSColin Finck     KxAcquireSpinLock(SpinLock);
33c2c66affSColin Finck     return OldIrql;
34c2c66affSColin Finck }
35c2c66affSColin Finck 
36c2c66affSColin Finck /*
37c2c66affSColin Finck  * @implemented
38c2c66affSColin Finck  */
39c2c66affSColin Finck KIRQL
40c2c66affSColin Finck NTAPI
KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock)41c2c66affSColin Finck KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock)
42c2c66affSColin Finck {
43c2c66affSColin Finck     KIRQL OldIrql;
44c2c66affSColin Finck 
45c2c66affSColin Finck     /* Raise to dispatch */
46c2c66affSColin Finck     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
47c2c66affSColin Finck 
48c2c66affSColin Finck     /* Acquire the lock and return */
49c2c66affSColin Finck     KxAcquireSpinLock(SpinLock);
50c2c66affSColin Finck     return OldIrql;
51c2c66affSColin Finck }
52c2c66affSColin Finck 
53c2c66affSColin Finck /*
54c2c66affSColin Finck  * @implemented
55c2c66affSColin Finck  */
56c2c66affSColin Finck VOID
57c2c66affSColin Finck NTAPI
KeReleaseSpinLock(PKSPIN_LOCK SpinLock,KIRQL OldIrql)58c2c66affSColin Finck KeReleaseSpinLock(PKSPIN_LOCK SpinLock,
59c2c66affSColin Finck                   KIRQL OldIrql)
60c2c66affSColin Finck {
61c2c66affSColin Finck     /* Release the lock and lower IRQL back */
62c2c66affSColin Finck     KxReleaseSpinLock(SpinLock);
63c2c66affSColin Finck     KeLowerIrql(OldIrql);
64c2c66affSColin Finck }
65c2c66affSColin Finck 
66c2c66affSColin Finck /*
67c2c66affSColin Finck  * @implemented
68c2c66affSColin Finck  */
69c2c66affSColin Finck KIRQL
KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)70c2c66affSColin Finck KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
71c2c66affSColin Finck {
72c2c66affSColin Finck     KIRQL OldIrql;
73c2c66affSColin Finck 
74c2c66affSColin Finck     /* Raise to dispatch */
75c2c66affSColin Finck     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
76c2c66affSColin Finck 
77c2c66affSColin Finck     /* Acquire the lock */
78c2c66affSColin Finck     KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
79c2c66affSColin Finck     return OldIrql;
80c2c66affSColin Finck }
81c2c66affSColin Finck 
82c2c66affSColin Finck /*
83c2c66affSColin Finck  * @implemented
84c2c66affSColin Finck  */
85c2c66affSColin Finck KIRQL
KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)86c2c66affSColin Finck KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
87c2c66affSColin Finck {
88c2c66affSColin Finck     KIRQL OldIrql;
89c2c66affSColin Finck 
90c2c66affSColin Finck     /* Raise to synch */
91c2c66affSColin Finck     KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
92c2c66affSColin Finck 
93c2c66affSColin Finck     /* Acquire the lock */
94c2c66affSColin Finck     KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
95c2c66affSColin Finck     return OldIrql;
96c2c66affSColin Finck }
97c2c66affSColin Finck 
98c2c66affSColin Finck /*
99c2c66affSColin Finck  * @implemented
100c2c66affSColin Finck  */
101c2c66affSColin Finck VOID
KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,IN PKLOCK_QUEUE_HANDLE LockHandle)102c2c66affSColin Finck KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,
103c2c66affSColin Finck                                IN PKLOCK_QUEUE_HANDLE LockHandle)
104c2c66affSColin Finck {
105c2c66affSColin Finck     /* Set up the lock */
106c2c66affSColin Finck     LockHandle->LockQueue.Next = NULL;
107c2c66affSColin Finck     LockHandle->LockQueue.Lock = SpinLock;
108c2c66affSColin Finck 
109c2c66affSColin Finck     /* Raise to dispatch */
110c2c66affSColin Finck     KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql);
111c2c66affSColin Finck 
112c2c66affSColin Finck     /* Acquire the lock */
113c2c66affSColin Finck     KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
114c2c66affSColin Finck }
115c2c66affSColin Finck 
116c2c66affSColin Finck 
117c2c66affSColin Finck /*
118c2c66affSColin Finck  * @implemented
119c2c66affSColin Finck  */
120c2c66affSColin Finck VOID
KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock,IN PKLOCK_QUEUE_HANDLE LockHandle)121c2c66affSColin Finck KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock,
122c2c66affSColin Finck                                            IN PKLOCK_QUEUE_HANDLE LockHandle)
123c2c66affSColin Finck {
124c2c66affSColin Finck     /* Set up the lock */
125c2c66affSColin Finck     LockHandle->LockQueue.Next = NULL;
126c2c66affSColin Finck     LockHandle->LockQueue.Lock = SpinLock;
127c2c66affSColin Finck 
128c2c66affSColin Finck     /* Raise to synch */
129c2c66affSColin Finck     KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql);
130c2c66affSColin Finck 
131c2c66affSColin Finck     /* Acquire the lock */
132c2c66affSColin Finck     KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK
133c2c66affSColin Finck }
134c2c66affSColin Finck 
135c2c66affSColin Finck 
136c2c66affSColin Finck /*
137c2c66affSColin Finck  * @implemented
138c2c66affSColin Finck  */
139c2c66affSColin Finck VOID
KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,IN KIRQL OldIrql)140c2c66affSColin Finck KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
141c2c66affSColin Finck                         IN KIRQL OldIrql)
142c2c66affSColin Finck {
143c2c66affSColin Finck     /* Release the lock */
144c2c66affSColin Finck     KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK
145c2c66affSColin Finck 
146c2c66affSColin Finck     /* Lower IRQL back */
147c2c66affSColin Finck     KeLowerIrql(OldIrql);
148c2c66affSColin Finck }
149c2c66affSColin Finck 
150c2c66affSColin Finck 
151c2c66affSColin Finck /*
152c2c66affSColin Finck  * @implemented
153c2c66affSColin Finck  */
154c2c66affSColin Finck VOID
KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)155c2c66affSColin Finck KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
156c2c66affSColin Finck {
157c2c66affSColin Finck     /* Simply lower IRQL back */
158c2c66affSColin Finck     KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK
159c2c66affSColin Finck     KeLowerIrql(LockHandle->OldIrql);
160c2c66affSColin Finck }
161c2c66affSColin Finck 
162c2c66affSColin Finck 
163c2c66affSColin Finck /*
164c2c66affSColin Finck  * @implemented
165c2c66affSColin Finck  */
166c2c66affSColin Finck BOOLEAN
KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,IN PKIRQL OldIrql)167c2c66affSColin Finck KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
168c2c66affSColin Finck                                          IN PKIRQL OldIrql)
169c2c66affSColin Finck {
170*2ed56fa7STimo Kreuzer     /* Raise to synch level */
171*2ed56fa7STimo Kreuzer     KeRaiseIrql(SYNCH_LEVEL, OldIrql);
172c2c66affSColin Finck 
173*2ed56fa7STimo Kreuzer #ifdef CONFIG_SMP
174*2ed56fa7STimo Kreuzer     // HACK
175*2ed56fa7STimo Kreuzer     return KeTryToAcquireSpinLockAtDpcLevel(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock);
176*2ed56fa7STimo Kreuzer #else
177c2c66affSColin Finck     /* Add an explicit memory barrier to prevent the compiler from reordering
178c2c66affSColin Finck        memory accesses across the borders of spinlocks */
179c2c66affSColin Finck     KeMemoryBarrierWithoutFence();
180c2c66affSColin Finck 
181c2c66affSColin Finck     /* Always return true on UP Machines */
182c2c66affSColin Finck     return TRUE;
183c2c66affSColin Finck #endif
184c2c66affSColin Finck }
185c2c66affSColin Finck 
186c2c66affSColin Finck /*
187c2c66affSColin Finck  * @implemented
188c2c66affSColin Finck  */
189c2c66affSColin Finck LOGICAL
KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,OUT PKIRQL OldIrql)190c2c66affSColin Finck KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
191c2c66affSColin Finck                              OUT PKIRQL OldIrql)
192c2c66affSColin Finck {
193*2ed56fa7STimo Kreuzer     /* Raise to dispatch level */
194c2c66affSColin Finck     KeRaiseIrql(DISPATCH_LEVEL, OldIrql);
195c2c66affSColin Finck 
196*2ed56fa7STimo Kreuzer #ifdef CONFIG_SMP
197*2ed56fa7STimo Kreuzer     // HACK
198*2ed56fa7STimo Kreuzer     return KeTryToAcquireSpinLockAtDpcLevel(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock);
199*2ed56fa7STimo Kreuzer #else
200*2ed56fa7STimo Kreuzer 
201c2c66affSColin Finck     /* Add an explicit memory barrier to prevent the compiler from reordering
202c2c66affSColin Finck        memory accesses across the borders of spinlocks */
203c2c66affSColin Finck     KeMemoryBarrierWithoutFence();
204c2c66affSColin Finck 
205c2c66affSColin Finck     /* Always return true on UP Machines */
206c2c66affSColin Finck     return TRUE;
207c2c66affSColin Finck #endif
208c2c66affSColin Finck }
209c2c66affSColin Finck 
210c2c66affSColin Finck /* EOF */
211