2004-08-15 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / ke / spinlock.c
1 /* $Id: spinlock.c,v 1.22 2004/08/15 16:39:05 chorns Exp $
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 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 3/6/98: Created
10 */
11
12 /*
13 * NOTE: On a uniprocessor machine spinlocks are implemented by raising
14 * the irq level
15 */
16
17 /* INCLUDES ****************************************************************/
18
19 #include <ntoskrnl.h>
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 KeRaiseIrql(Interrupt->SynchLevel, &oldlvl);
46 KiAcquireSpinLock(Interrupt->IrqLock);
47
48 ret = SynchronizeRoutine(SynchronizeContext);
49
50 KiReleaseSpinLock(Interrupt->IrqLock);
51 KeLowerIrql(oldlvl);
52
53 return(ret);
54 }
55
56 /*
57 * @unimplemented
58 */
59 STDCALL
60 KIRQL
61 KeAcquireInterruptSpinLock(
62 IN PKINTERRUPT Interrupt
63 )
64 {
65 UNIMPLEMENTED;
66 return 0;
67 }
68
69 /*
70 * @implemented
71 */
72 VOID STDCALL
73 KeInitializeSpinLock (PKSPIN_LOCK SpinLock)
74 /*
75 * FUNCTION: Initalizes a spinlock
76 * ARGUMENTS:
77 * SpinLock = Caller supplied storage for the spinlock
78 */
79 {
80 *SpinLock = 0;
81 }
82
83 #undef KefAcquireSpinLockAtDpcLevel
84
85 /*
86 * @implemented
87 */
88 VOID FASTCALL
89 KefAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
90 {
91 assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
92 KiAcquireSpinLock(SpinLock);
93 }
94
95 #undef KeAcquireSpinLockAtDpcLevel
96
97 /*
98 * @implemented
99 */
100 VOID STDCALL
101 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
102 /*
103 * FUNCTION: Acquires a spinlock when the caller is already running at
104 * dispatch level
105 * ARGUMENTS:
106 * SpinLock = Spinlock to acquire
107 */
108 {
109 KefAcquireSpinLockAtDpcLevel(SpinLock);
110 }
111
112
113 /*
114 * @unimplemented
115 */
116 VOID
117 FASTCALL
118 KeAcquireInStackQueuedSpinLockAtDpcLevel(
119 IN PKSPIN_LOCK SpinLock,
120 IN PKLOCK_QUEUE_HANDLE LockHandle
121 )
122 {
123 UNIMPLEMENTED;
124 }
125
126
127 #undef KefReleaseSpinLockFromDpcLevel
128
129 /*
130 * @implemented
131 */
132 VOID FASTCALL
133 KefReleaseSpinLockFromDpcLevel(PKSPIN_LOCK SpinLock)
134 {
135 assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
136 KiReleaseSpinLock(SpinLock);
137 }
138
139 #undef KeReleaseSpinLockFromDpcLevel
140
141 /*
142 * @implemented
143 */
144 VOID STDCALL
145 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
146 /*
147 * FUNCTION: Releases a spinlock when the caller was running at dispatch
148 * level before acquiring it
149 * ARGUMENTS:
150 * SpinLock = Spinlock to release
151 */
152 {
153 KefReleaseSpinLockFromDpcLevel(SpinLock);
154 }
155
156 /*
157 * @unimplemented
158 */
159 VOID
160 FASTCALL
161 KeReleaseInStackQueuedSpinLockFromDpcLevel(
162 IN PKLOCK_QUEUE_HANDLE LockHandle
163 )
164 {
165 UNIMPLEMENTED;
166 }
167
168 /*
169 * @implemented
170 */
171 VOID FASTCALL
172 KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
173 {
174 ULONG i;
175
176 /*
177 * FIXME: This depends on gcc assembling this test to a single load from
178 * the spinlock's value.
179 */
180 if (*SpinLock >= 2)
181 {
182 DbgPrint("Lock %x has bad value %x\n", SpinLock, *SpinLock);
183 KEBUGCHECK(0);
184 }
185
186 while ((i = InterlockedExchange((LONG *)SpinLock, 1)) == 1)
187 {
188 #ifndef MP
189 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
190 KEBUGCHECK(0);
191 #else /* not MP */
192 /* Avoid reading the value again too fast */
193 #endif /* MP */
194 }
195 }
196
197 /*
198 * @unimplemented
199 */
200 STDCALL
201 VOID
202 KeReleaseInterruptSpinLock(
203 IN PKINTERRUPT Interrupt,
204 IN KIRQL OldIrql
205 )
206 {
207 UNIMPLEMENTED;
208 }
209
210 /*
211 * @implemented
212 */
213 VOID FASTCALL
214 KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
215 {
216 if (*SpinLock != 1)
217 {
218 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
219 KEBUGCHECK(0);
220 }
221 (void)InterlockedExchange((LONG *)SpinLock, 0);
222 }
223
224 /* EOF */