Reintegrate header-work branch. Important changes include continued work on headers...
[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 = (PVOID)_InterlockedCompareExchange((PLONG)Head,
41 (LONG)Entry,
42 (LONG)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 = (PVOID)_InterlockedCompareExchange((PLONG)Head,
61 (LONG)FirstEntry->Next,
62 (LONG)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 (PVOID)_InterlockedExchange((PLONG)&ListHead->Next.Next, (LONG)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 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 OldHead = ListHead->Next;
273 PushEntryList(ListHead, ListEntry);
274 KeReleaseSpinLock(Lock, OldIrql);
275 return OldHead;
276 }
277
278 PLIST_ENTRY
279 NTAPI
280 ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead,
281 IN PKSPIN_LOCK Lock)
282 {
283 KIRQL OldIrql;
284 PLIST_ENTRY OldHead = NULL;
285 KeAcquireSpinLock(Lock, &OldIrql);
286 if (!IsListEmpty(ListHead)) OldHead = RemoveHeadList(ListHead);
287 KeReleaseSpinLock(Lock, OldIrql);
288 return OldHead;
289 }
290
291 VOID
292 FASTCALL
293 ExInterlockedAddLargeStatistic(IN PLONGLONG Addend,
294 IN ULONG Increment)
295 {
296 UNIMPLEMENTED;
297 }
298
299 LONGLONG
300 FASTCALL
301 ExInterlockedCompareExchange64(IN OUT LONGLONG volatile *Destination,
302 IN PLONGLONG Exchange,
303 IN PLONGLONG Comparand,
304 IN PKSPIN_LOCK Lock)
305 {
306 KIRQL OldIrql;
307 LONGLONG Result;
308
309 KeAcquireSpinLock(Lock, &OldIrql);
310 Result = *Destination;
311 if (*Destination == *Comparand) *Destination = *Exchange;
312 KeReleaseSpinLock(Lock, OldIrql);
313 return Result;
314 }
315
316 VOID
317 NTAPI
318 READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register,
319 IN PUCHAR Buffer,
320 IN ULONG Count)
321 {
322 PUCHAR registerBuffer = Register;
323 PUCHAR readBuffer = Buffer;
324 ULONG readCount;
325
326 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
327 {
328 *readBuffer = *(volatile UCHAR * const)registerBuffer;
329 }
330 }
331
332 VOID
333 NTAPI
334 READ_REGISTER_BUFFER_ULONG(IN PULONG Register,
335 IN PULONG Buffer,
336 IN ULONG Count)
337 {
338 PULONG registerBuffer = Register;
339 PULONG readBuffer = Buffer;
340 ULONG readCount;
341
342 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
343 {
344 *readBuffer = *(volatile ULONG * const)registerBuffer;
345 }
346 }
347
348 VOID
349 NTAPI
350 READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register,
351 IN PUSHORT Buffer,
352 IN ULONG Count)
353 {
354 PUSHORT registerBuffer = Register;
355 PUSHORT readBuffer = Buffer;
356 ULONG readCount;
357
358 for (readCount = Count; readCount--; readBuffer++, registerBuffer++)
359 {
360 *readBuffer = *(volatile USHORT * const)registerBuffer;
361 }
362 }
363
364 UCHAR
365 NTAPI
366 READ_REGISTER_UCHAR(IN PUCHAR Register)
367 {
368 return *(volatile UCHAR * const)Register;
369 }
370
371 ULONG
372 NTAPI
373 READ_REGISTER_ULONG(IN PULONG Register)
374 {
375 return *(volatile ULONG * const)Register;
376 }
377
378 USHORT
379 NTAPI
380 READ_REGISTER_USHORT(IN PUSHORT Register)
381 {
382 return *(volatile USHORT * const)Register;
383 }
384
385 VOID
386 NTAPI
387 WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register,
388 IN PUCHAR Buffer,
389 IN ULONG Count)
390 {
391 PUCHAR registerBuffer = Register;
392 PUCHAR writeBuffer = Buffer;
393 ULONG writeCount;
394 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
395 {
396 *(volatile UCHAR * const)registerBuffer = *writeBuffer;
397 }
398 KeFlushWriteBuffer();
399 }
400
401 VOID
402 NTAPI
403 WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register,
404 IN PULONG Buffer,
405 IN ULONG Count)
406 {
407 PULONG registerBuffer = Register;
408 PULONG writeBuffer = Buffer;
409 ULONG writeCount;
410 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
411 {
412 *(volatile ULONG * const)registerBuffer = *writeBuffer;
413 }
414 KeFlushWriteBuffer();
415 }
416
417 VOID
418 NTAPI
419 WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register,
420 IN PUSHORT Buffer,
421 IN ULONG Count)
422 {
423 PUSHORT registerBuffer = Register;
424 PUSHORT writeBuffer = Buffer;
425 ULONG writeCount;
426 for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++)
427 {
428 *(volatile USHORT * const)registerBuffer = *writeBuffer;
429 }
430 KeFlushWriteBuffer();
431 }
432
433 VOID
434 NTAPI
435 WRITE_REGISTER_UCHAR(IN PUCHAR Register,
436 IN UCHAR Value)
437 {
438 *(volatile UCHAR * const)Register = Value;
439 KeFlushWriteBuffer();
440 }
441
442 VOID
443 NTAPI
444 WRITE_REGISTER_ULONG(IN PULONG Register,
445 IN ULONG Value)
446 {
447 *(volatile ULONG * const)Register = Value;
448 KeFlushWriteBuffer();
449 }
450
451 VOID
452 NTAPI
453 WRITE_REGISTER_USHORT(IN PUSHORT Register,
454 IN USHORT Value)
455 {
456 *(volatile USHORT * const)Register = Value;
457 KeFlushWriteBuffer();
458 }
459
460 #endif