Fix prototype
[reactos.git] / reactos / ntoskrnl / ex / fastinterlck.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ex/fastinterlck.c
5 * PURPOSE: Portable Ex*Interlocked and REGISTER routines for non-x86
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #if defined(_ARM_) || defined(_PPC_) || defined(NTOS_USE_GENERICS)
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 #undef ExInterlockedPushEntrySList
18 #undef ExInterlockedPopEntrySList
19 #undef ExInterlockedAddULong
20 #undef ExInterlockedIncrementLong
21 #undef ExInterlockedDecrementLong
22
23 /* FUNCTIONS ******************************************************************/
24
25 PSLIST_ENTRY
26 NTAPI
27 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
28 IN PSLIST_ENTRY ListEntry)
29 {
30
31 PSINGLE_LIST_ENTRY FirstEntry, NextEntry;
32 PSINGLE_LIST_ENTRY Entry = (PVOID)ListEntry, Head = (PVOID)ListHead;
33
34 FirstEntry = Head->Next;
35 do
36 {
37 Entry->Next = FirstEntry;
38 NextEntry = FirstEntry;
39 FirstEntry = (PVOID)_InterlockedCompareExchange((PLONG)Head,
40 (LONG)Entry,
41 (LONG)FirstEntry);
42 } while (FirstEntry != NextEntry);
43
44 return FirstEntry;
45 }
46
47 PSLIST_ENTRY
48 NTAPI
49 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead)
50 {
51 PSINGLE_LIST_ENTRY FirstEntry, NextEntry, Head = (PVOID)ListHead;
52
53 FirstEntry = Head->Next;
54 do
55 {
56 if (!FirstEntry) return NULL;
57
58 NextEntry = FirstEntry;
59 FirstEntry = (PVOID)_InterlockedCompareExchange((PLONG)Head,
60 (LONG)FirstEntry->Next,
61 (LONG)FirstEntry);
62 } while (FirstEntry != NextEntry);
63
64 return FirstEntry;
65 }
66
67 PSINGLE_LIST_ENTRY
68 FASTCALL
69 ExInterlockedFlushSList(IN PSLIST_HEADER ListHead)
70 {
71 return (PVOID)_InterlockedExchange((PLONG)&ListHead->Next.Next, (LONG)NULL);
72 }
73
74 PSLIST_ENTRY
75 FASTCALL
76 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
77 IN PSLIST_ENTRY ListEntry)
78 IN PKSPIN_LOCK Lock)
79 {
80 return InterlockedPushEntrySList(ListHead, ListEntry);
81 }
82
83 PSINGLE_LIST_ENTRY
84 NTAPI
85 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead,
86 IN PKSPIN_LOCK Lock)
87 {
88 return InterlockedPopEntrySList(ListHead);
89 }
90
91 ULONG
92 FASTCALL
93 ExfInterlockedAddUlong(IN PULONG Addend,
94 IN ULONG Increment,
95 PKSPIN_LOCK Lock)
96 {
97 KIRQL OldIrql;
98 KeAcquireSpinLock(Lock, &OldIrql);
99 *Addend += Increment;
100 KeReleaseSpinLock(Lock, OldIrql);
101 return *Addend;
102 }
103
104 LONGLONG
105 FASTCALL
106 ExfInterlockedCompareExchange64(IN OUT LONGLONG volatile *Destination,
107 IN PLONGLONG Exchange,
108 IN PLONGLONG Comperand)
109 {
110 LONGLONG Result;
111
112 Result = *Destination;
113 if (*Destination == Result) *Destination = *Exchange;
114 return Result;
115 }
116
117 PLIST_ENTRY
118 FASTCALL
119 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
120 IN PLIST_ENTRY ListEntry,
121 IN PKSPIN_LOCK Lock)
122 {
123 KIRQL OldIrql;
124 PLIST_ENTRY OldHead = NULL;
125 KeAcquireSpinLock(Lock, &OldIrql);
126 if (!IsListEmpty(ListHead)) OldHead = ListEntry->Flink;
127 InsertHeadList(ListHead, ListEntry);
128 KeReleaseSpinLock(Lock, OldIrql);
129 return OldHead;
130 }
131
132 PLIST_ENTRY
133 FASTCALL
134 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
135 IN PLIST_ENTRY ListEntry,
136 IN PKSPIN_LOCK Lock)
137 {
138 KIRQL OldIrql;
139 PLIST_ENTRY OldHead = NULL;
140 KeAcquireSpinLock(Lock, &OldIrql);
141 if (!IsListEmpty(ListHead)) OldHead = ListEntry->Blink;
142 InsertTailList(ListHead, ListEntry);
143 KeReleaseSpinLock(Lock, OldIrql);
144 return OldHead;
145 }
146
147 PSINGLE_LIST_ENTRY
148 FASTCALL
149 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
150 IN PKSPIN_LOCK Lock)
151 {
152 UNIMPLEMENTED;
153 return NULL;
154 }
155
156 PSINGLE_LIST_ENTRY
157 FASTCALL
158 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
159 IN PSINGLE_LIST_ENTRY ListEntry,
160 IN PKSPIN_LOCK Lock)
161 {
162 UNIMPLEMENTED;
163 return NULL;
164 }
165
166 PLIST_ENTRY
167 FASTCALL
168 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead,
169 IN PKSPIN_LOCK Lock)
170 {
171 return ExInterlockedRemoveHeadList(ListHead, Lock);
172 }
173
174 LARGE_INTEGER
175 NTAPI
176 ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend,
177 IN LARGE_INTEGER Increment,
178 IN PKSPIN_LOCK Lock)
179 {
180 LARGE_INTEGER Integer = {{0}};
181 UNIMPLEMENTED;
182 return Integer;
183 }
184
185 ULONG
186 NTAPI
187 ExInterlockedAddUlong(IN PULONG Addend,
188 IN ULONG Increment,
189 PKSPIN_LOCK Lock)
190 {
191 return (ULONG)_InterlockedExchangeAdd((PLONG)Addend, Increment);
192 }
193
194 INTERLOCKED_RESULT
195 NTAPI
196 ExInterlockedIncrementLong(IN PLONG Addend,
197 IN PKSPIN_LOCK Lock)
198 {
199 return _InterlockedIncrement(Addend);
200 }
201
202 INTERLOCKED_RESULT
203 NTAPI
204 ExInterlockedDecrementLong(IN PLONG Addend,
205 IN PKSPIN_LOCK Lock)
206 {
207 return _InterlockedDecrement(Addend);
208 }
209
210 ULONG
211 NTAPI
212 ExInterlockedExchangeUlong(IN PULONG Target,
213 IN ULONG Value,
214 IN PKSPIN_LOCK Lock)
215 {
216 return (ULONG)_InterlockedExchange((PLONG)Target, Value);
217 }
218
219 PLIST_ENTRY
220 NTAPI
221 ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
222 IN PLIST_ENTRY ListEntry,
223 IN PKSPIN_LOCK Lock)
224 {
225 KIRQL OldIrql;
226 PLIST_ENTRY OldHead = NULL;
227 KeAcquireSpinLock(Lock, &OldIrql);
228 if (!IsListEmpty(ListHead)) OldHead = ListEntry->Flink;
229 InsertHeadList(ListHead, ListEntry);
230 KeReleaseSpinLock(Lock, OldIrql);
231 return OldHead;
232 }
233
234 PLIST_ENTRY
235 NTAPI
236 ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
237 IN PLIST_ENTRY ListEntry,
238 IN PKSPIN_LOCK Lock)
239 {
240 KIRQL OldIrql;
241 PLIST_ENTRY OldHead = NULL;
242 KeAcquireSpinLock(Lock, &OldIrql);
243 if (!IsListEmpty(ListHead)) OldHead = ListEntry->Blink;
244 InsertTailList(ListHead, ListEntry);
245 KeReleaseSpinLock(Lock, OldIrql);
246 return OldHead;
247 }
248
249 PSINGLE_LIST_ENTRY
250 NTAPI
251 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
252 IN PKSPIN_LOCK Lock)
253 {
254 KIRQL OldIrql;
255 PSINGLE_LIST_ENTRY OldHead = NULL;
256 KeAcquireSpinLock(Lock, &OldIrql);
257 if (!ListHead->Next) OldHead = PopEntryList(ListHead);
258 KeReleaseSpinLock(Lock, OldIrql);
259 return OldHead;
260 }
261
262 PSINGLE_LIST_ENTRY
263 NTAPI
264 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
265 IN PSINGLE_LIST_ENTRY ListEntry,
266 IN PKSPIN_LOCK Lock)
267 {
268 KIRQL OldIrql;
269 PSINGLE_LIST_ENTRY OldHead = NULL;
270 KeAcquireSpinLock(Lock, &OldIrql);
271 if (!ListHead->Next) OldHead = PushEntryList(ListHead, ListEntry);
272 KeReleaseSpinLock(Lock, OldIrql);
273 return OldHead;
274 }
275
276 PLIST_ENTRY
277 NTAPI
278 ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead,
279 IN PKSPIN_LOCK Lock)
280 {
281 KIRQL OldIrql;
282 PLIST_ENTRY OldHead = NULL;
283 KeAcquireSpinLock(Lock, &OldIrql);
284 if (!IsListEmpty(ListHead)) OldHead = RemoveHeadList(ListHead);
285 KeReleaseSpinLock(Lock, OldIrql);
286 return OldHead;
287 }
288
289 VOID
290 FASTCALL
291 ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend,
292 IN ULONG Increment)
293 {
294 UNIMPLEMENTED;
295 }
296
297 LONGLONG
298 FASTCALL
299 ExInterlockedCompareExchange64(IN OUT PLONGLONG Destination,
300 IN PLONGLONG Exchange,
301 IN PLONGLONG Comparand,
302 IN PKSPIN_LOCK Lock)
303 {
304 KIRQL OldIrql;
305 LONGLONG Result;
306
307 KeAcquireSpinLock(Lock, &OldIrql);
308 Result = *Destination;
309 if (*Destination == Result) *Destination = *Exchange;
310 KeReleaseSpinLock(Lock, OldIrql);
311 return Result;
312 }
313
314 VOID
315 NTAPI
316 READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register,
317 IN PUCHAR Buffer,
318 IN ULONG Count)
319 {
320 PUCHAR registerBuffer = Register;
321 PUCHAR readBuffer = Buffer;
322 ULONG readCount;
323
324 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
325 {
326 *readBuffer = *(volatile UCHAR * const)registerBuffer;
327 }
328 }
329
330 VOID
331 NTAPI
332 READ_REGISTER_BUFFER_ULONG(IN PULONG Register,
333 IN PULONG Buffer,
334 IN ULONG Count)
335 {
336 PULONG registerBuffer = Register;
337 PULONG readBuffer = Buffer;
338 ULONG readCount;
339
340 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
341 {
342 *readBuffer = *(volatile ULONG * const)registerBuffer;
343 }
344 }
345
346 VOID
347 NTAPI
348 READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register,
349 IN PUSHORT Buffer,
350 IN ULONG Count)
351 {
352 PUSHORT registerBuffer = Register;
353 PUSHORT readBuffer = Buffer;
354 ULONG readCount;
355
356 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
357 {
358 *readBuffer = *(volatile USHORT * const)registerBuffer;
359 }
360 }
361
362 UCHAR
363 NTAPI
364 READ_REGISTER_UCHAR(IN PUCHAR Register)
365 {
366 return *(volatile UCHAR * const)Register;
367 }
368
369 ULONG
370 NTAPI
371 READ_REGISTER_ULONG(IN PULONG Register)
372 {
373 return *(volatile ULONG * const)Register;
374 }
375
376 USHORT
377 NTAPI
378 READ_REGISTER_USHORT(IN PUSHORT Register)
379 {
380 return *(volatile USHORT * const)Register;
381 }
382
383 VOID
384 NTAPI
385 WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register,
386 IN PUCHAR Buffer,
387 IN ULONG Count)
388 {
389 PUCHAR registerBuffer = Register;
390 PUCHAR writeBuffer = Buffer;
391 ULONG writeCount;
392 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
393 {
394 *(volatile UCHAR * const)registerBuffer = *writeBuffer;
395 }
396 KeFlushWriteBuffer();
397 }
398
399 VOID
400 NTAPI
401 WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register,
402 IN PULONG Buffer,
403 IN ULONG Count)
404 {
405 PULONG registerBuffer = Register;
406 PULONG writeBuffer = Buffer;
407 ULONG writeCount;
408 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
409 {
410 *(volatile ULONG * const)registerBuffer = *writeBuffer;
411 }
412 KeFlushWriteBuffer();
413 }
414
415 VOID
416 NTAPI
417 WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register,
418 IN PUSHORT Buffer,
419 IN ULONG Count)
420 {
421 PUSHORT registerBuffer = Register;
422 PUSHORT writeBuffer = Buffer;
423 ULONG writeCount;
424 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
425 {
426 *(volatile USHORT * const)registerBuffer = *writeBuffer;
427 }
428 KeFlushWriteBuffer();
429 }
430
431 VOID
432 NTAPI
433 WRITE_REGISTER_UCHAR(IN PUCHAR Register,
434 IN UCHAR Value)
435 {
436 *(volatile UCHAR * const)Register = Value;
437 KeFlushWriteBuffer();
438 }
439
440 VOID
441 NTAPI
442 WRITE_REGISTER_ULONG(IN PULONG Register,
443 IN ULONG Value)
444 {
445 *(volatile ULONG * const)Register = Value;
446 KeFlushWriteBuffer();
447 }
448
449 VOID
450 NTAPI
451 WRITE_REGISTER_USHORT(IN PUSHORT Register,
452 IN USHORT Value)
453 {
454 *(volatile USHORT * const)Register = Value;
455 KeFlushWriteBuffer();
456 }
457
458 #endif