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