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