Fix some ntoskrnl things, like using Rtl instead of RosRtl, and undefining ROUND...
[reactos.git] / reactos / ntoskrnl / ke / spinlock.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/spinlock.c
6 * PURPOSE: Implements spinlocks
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /*
12 * NOTE: On a uniprocessor machine spinlocks are implemented by raising
13 * the irq level
14 */
15
16 /* INCLUDES ****************************************************************/
17
18 #include <ntoskrnl.h>
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* FUNCTIONS ***************************************************************/
23
24 /*
25 * @implemented
26 */
27 BOOLEAN STDCALL
28 KeSynchronizeExecution (PKINTERRUPT Interrupt,
29 PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
30 PVOID SynchronizeContext)
31 /*
32 * FUNCTION: Synchronizes the execution of a given routine with the ISR
33 * of a given interrupt object
34 * ARGUMENTS:
35 * Interrupt = Interrupt object to synchronize with
36 * SynchronizeRoutine = Routine to call whose execution is
37 * synchronized with the ISR
38 * SynchronizeContext = Parameter to pass to the synchronized routine
39 * RETURNS: TRUE if the operation succeeded
40 */
41 {
42 KIRQL oldlvl;
43 BOOLEAN ret;
44
45 oldlvl = KeAcquireInterruptSpinLock(Interrupt);
46
47 ret = SynchronizeRoutine(SynchronizeContext);
48
49 KeReleaseInterruptSpinLock(Interrupt, oldlvl);
50
51 return(ret);
52 }
53
54 /*
55 * @implemented
56 */
57 KIRQL
58 STDCALL
59 KeAcquireInterruptSpinLock(
60 IN PKINTERRUPT Interrupt
61 )
62 {
63 KIRQL oldIrql;
64
65 //KeRaiseIrql(Interrupt->SynchronizeIrql, &oldIrql);
66 KeRaiseIrql(Interrupt->SynchLevel, &oldIrql);
67 KiAcquireSpinLock(Interrupt->ActualLock);
68 return oldIrql;
69 }
70
71 /*
72 * @implemented
73 */
74 VOID STDCALL
75 KeInitializeSpinLock (PKSPIN_LOCK SpinLock)
76 /*
77 * FUNCTION: Initalizes a spinlock
78 * ARGUMENTS:
79 * SpinLock = Caller supplied storage for the spinlock
80 */
81 {
82 *SpinLock = 0;
83 }
84
85 #undef KefAcquireSpinLockAtDpcLevel
86
87 /*
88 * @implemented
89 */
90 VOID FASTCALL
91 KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
92 {
93 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
94 KiAcquireSpinLock(SpinLock);
95 }
96
97 #undef KeAcquireSpinLockAtDpcLevel
98
99 /*
100 * @implemented
101 */
102 VOID STDCALL
103 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
104 /*
105 * FUNCTION: Acquires a spinlock when the caller is already running at
106 * dispatch level
107 * ARGUMENTS:
108 * SpinLock = Spinlock to acquire
109 */
110 {
111 KefAcquireSpinLockAtDpcLevel(SpinLock);
112 }
113
114
115 /*
116 * @unimplemented
117 */
118 VOID
119 FASTCALL
120 KeAcquireInStackQueuedSpinLockAtDpcLevel(
121 IN PKSPIN_LOCK SpinLock,
122 IN PKLOCK_QUEUE_HANDLE LockHandle
123 )
124 {
125 UNIMPLEMENTED;
126 }
127
128
129 #undef KefReleaseSpinLockFromDpcLevel
130
131 /*
132 * @implemented
133 */
134 VOID FASTCALL
135 KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
136 {
137 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
138 KiReleaseSpinLock(SpinLock);
139 }
140
141 #undef KeReleaseSpinLockFromDpcLevel
142
143 /*
144 * @implemented
145 */
146 VOID STDCALL
147 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
148 /*
149 * FUNCTION: Releases a spinlock when the caller was running at dispatch
150 * level before acquiring it
151 * ARGUMENTS:
152 * SpinLock = Spinlock to release
153 */
154 {
155 KefReleaseSpinLockFromDpcLevel(SpinLock);
156 }
157
158 /*
159 * @unimplemented
160 */
161 VOID
162 FASTCALL
163 KeReleaseInStackQueuedSpinLockFromDpcLevel(
164 IN PKLOCK_QUEUE_HANDLE LockHandle
165 )
166 {
167 UNIMPLEMENTED;
168 }
169
170 /*
171 * @implemented
172 */
173 VOID FASTCALL
174 KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
175 {
176 ULONG i;
177
178 /*
179 * FIXME: This depends on gcc assembling this test to a single load from
180 * the spinlock's value.
181 */
182 ASSERT(*SpinLock < 2);
183
184 while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
185 {
186 #ifdef CONFIG_SMP
187 /* Avoid reading the value again too fast */
188 #if 1
189 __asm__ __volatile__ ("1:\n\t"
190 "cmpl $0,(%0)\n\t"
191 "jne 1b\n\t"
192 :
193 : "r" (SpinLock));
194 #else
195 while (0 != *(volatile KSPIN_LOCK*)SpinLock);
196 #endif
197 #else
198 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
199 KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED, (ULONG)SpinLock, 0, 0, 0);
200 #endif /* CONFIG_SMP */
201 }
202 }
203
204 /*
205 * @implemented
206 */
207 VOID
208 STDCALL
209 KeReleaseInterruptSpinLock(
210 IN PKINTERRUPT Interrupt,
211 IN KIRQL OldIrql
212 )
213 {
214 KiReleaseSpinLock(Interrupt->ActualLock);
215 KeLowerIrql(OldIrql);
216 }
217
218 /*
219 * @implemented
220 */
221 VOID FASTCALL
222 KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
223 {
224 if (*SpinLock != 1)
225 {
226 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
227 KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED, (ULONG)SpinLock, 0, 0, 0);
228 }
229 (void)InterlockedExchangeUL(SpinLock, 0);
230 }
231
232 /* EOF */