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