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
9 /* INCLUDES *******************************************************************/
11 #if defined(_ARM_) || defined(_PPC_) || defined(NTOS_USE_GENERICS)
17 #undef ExInterlockedPushEntrySList
18 #undef ExInterlockedPopEntrySList
19 #undef ExInterlockedAddULong
20 #undef ExInterlockedIncrementLong
21 #undef ExInterlockedDecrementLong
23 /* FUNCTIONS ******************************************************************/
27 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
28 IN PSLIST_ENTRY ListEntry
)
31 PSINGLE_LIST_ENTRY FirstEntry
, NextEntry
;
32 PSINGLE_LIST_ENTRY Entry
= (PVOID
)ListEntry
, Head
= (PVOID
)ListHead
;
34 FirstEntry
= Head
->Next
;
37 Entry
->Next
= FirstEntry
;
38 NextEntry
= FirstEntry
;
39 FirstEntry
= (PVOID
)_InterlockedCompareExchange((PLONG
)Head
,
42 } while (FirstEntry
!= NextEntry
);
49 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
51 PSINGLE_LIST_ENTRY FirstEntry
, NextEntry
, Head
= (PVOID
)ListHead
;
53 FirstEntry
= Head
->Next
;
56 if (!FirstEntry
) return NULL
;
58 NextEntry
= FirstEntry
;
59 FirstEntry
= (PVOID
)_InterlockedCompareExchange((PLONG
)Head
,
60 (LONG
)FirstEntry
->Next
,
62 } while (FirstEntry
!= NextEntry
);
69 ExInterlockedFlushSList(IN PSLIST_HEADER ListHead
)
71 return (PVOID
)_InterlockedExchange((PLONG
)&ListHead
->Next
.Next
, (LONG
)NULL
);
76 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
77 IN PSLIST_ENTRY ListEntry
)
79 return InterlockedPushEntrySList(ListHead
, ListEntry
);
84 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
87 return InterlockedPopEntrySList(ListHead
);
92 ExfInterlockedAddUlong(IN PULONG Addend
,
97 KeAcquireSpinLock(Lock
, &OldIrql
);
99 KeReleaseSpinLock(Lock
, OldIrql
);
105 ExfInterlockedCompareExchange64(IN OUT LONGLONG
volatile *Destination
,
106 IN PLONGLONG Exchange
,
107 IN PLONGLONG Comperand
)
111 Result
= *Destination
;
112 if (*Destination
== Result
) *Destination
= *Exchange
;
118 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
119 IN PLIST_ENTRY ListEntry
,
123 PLIST_ENTRY OldHead
= NULL
;
124 KeAcquireSpinLock(Lock
, &OldIrql
);
125 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
126 InsertHeadList(ListHead
, ListEntry
);
127 KeReleaseSpinLock(Lock
, OldIrql
);
133 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
134 IN PLIST_ENTRY ListEntry
,
138 PLIST_ENTRY OldHead
= NULL
;
139 KeAcquireSpinLock(Lock
, &OldIrql
);
140 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
141 InsertTailList(ListHead
, ListEntry
);
142 KeReleaseSpinLock(Lock
, OldIrql
);
148 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
157 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
158 IN PSINGLE_LIST_ENTRY ListEntry
,
167 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
170 return ExInterlockedRemoveHeadList(ListHead
, Lock
);
175 ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend
,
176 IN LARGE_INTEGER Increment
,
179 LARGE_INTEGER Integer
= {{0}};
186 ExInterlockedAddUlong(IN PULONG Addend
,
190 return (ULONG
)_InterlockedExchangeAdd((PLONG
)Addend
, Increment
);
195 ExInterlockedIncrementLong(IN PLONG Addend
,
198 return _InterlockedIncrement(Addend
);
203 ExInterlockedDecrementLong(IN PLONG Addend
,
206 return _InterlockedDecrement(Addend
);
211 ExInterlockedExchangeUlong(IN PULONG Target
,
215 return (ULONG
)_InterlockedExchange((PLONG
)Target
, Value
);
220 ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
221 IN PLIST_ENTRY ListEntry
,
225 PLIST_ENTRY OldHead
= NULL
;
226 KeAcquireSpinLock(Lock
, &OldIrql
);
227 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
228 InsertHeadList(ListHead
, ListEntry
);
229 KeReleaseSpinLock(Lock
, OldIrql
);
235 ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
236 IN PLIST_ENTRY ListEntry
,
240 PLIST_ENTRY OldHead
= NULL
;
241 KeAcquireSpinLock(Lock
, &OldIrql
);
242 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
243 InsertTailList(ListHead
, ListEntry
);
244 KeReleaseSpinLock(Lock
, OldIrql
);
250 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
254 PSINGLE_LIST_ENTRY OldHead
= NULL
;
255 KeAcquireSpinLock(Lock
, &OldIrql
);
256 if (!ListHead
->Next
) OldHead
= PopEntryList(ListHead
);
257 KeReleaseSpinLock(Lock
, OldIrql
);
263 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
264 IN PSINGLE_LIST_ENTRY ListEntry
,
268 PSINGLE_LIST_ENTRY OldHead
= NULL
;
269 KeAcquireSpinLock(Lock
, &OldIrql
);
270 if (!ListHead
->Next
) OldHead
= PushEntryList(ListHead
, ListEntry
);
271 KeReleaseSpinLock(Lock
, OldIrql
);
277 ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
281 PLIST_ENTRY OldHead
= NULL
;
282 KeAcquireSpinLock(Lock
, &OldIrql
);
283 if (!IsListEmpty(ListHead
)) OldHead
= RemoveHeadList(ListHead
);
284 KeReleaseSpinLock(Lock
, OldIrql
);
290 ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend
,
298 ExInterlockedCompareExchange64(IN OUT PLONGLONG Destination
,
299 IN PLONGLONG Exchange
,
300 IN PLONGLONG Comparand
,
306 KeAcquireSpinLock(Lock
, &OldIrql
);
307 Result
= *Destination
;
308 if (*Destination
== Result
) *Destination
= *Exchange
;
309 KeReleaseSpinLock(Lock
, OldIrql
);
315 READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
319 PUCHAR registerBuffer
= Register
;
320 PUCHAR readBuffer
= Buffer
;
323 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
325 *readBuffer
= *(volatile UCHAR
* const)registerBuffer
;
331 READ_REGISTER_BUFFER_ULONG(IN PULONG Register
,
335 PULONG registerBuffer
= Register
;
336 PULONG readBuffer
= Buffer
;
339 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
341 *readBuffer
= *(volatile ULONG
* const)registerBuffer
;
347 READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
351 PUSHORT registerBuffer
= Register
;
352 PUSHORT readBuffer
= Buffer
;
355 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
357 *readBuffer
= *(volatile USHORT
* const)registerBuffer
;
363 READ_REGISTER_UCHAR(IN PUCHAR Register
)
365 return *(volatile UCHAR
* const)Register
;
370 READ_REGISTER_ULONG(IN PULONG Register
)
372 return *(volatile ULONG
* const)Register
;
377 READ_REGISTER_USHORT(IN PUSHORT Register
)
379 return *(volatile USHORT
* const)Register
;
384 WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
388 PUCHAR registerBuffer
= Register
;
389 PUCHAR writeBuffer
= Buffer
;
391 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
393 *(volatile UCHAR
* const)registerBuffer
= *writeBuffer
;
395 KeFlushWriteBuffer();
400 WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register
,
404 PULONG registerBuffer
= Register
;
405 PULONG writeBuffer
= Buffer
;
407 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
409 *(volatile ULONG
* const)registerBuffer
= *writeBuffer
;
411 KeFlushWriteBuffer();
416 WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
420 PUSHORT registerBuffer
= Register
;
421 PUSHORT writeBuffer
= Buffer
;
423 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
425 *(volatile USHORT
* const)registerBuffer
= *writeBuffer
;
427 KeFlushWriteBuffer();
432 WRITE_REGISTER_UCHAR(IN PUCHAR Register
,
435 *(volatile UCHAR
* const)Register
= Value
;
436 KeFlushWriteBuffer();
441 WRITE_REGISTER_ULONG(IN PULONG Register
,
444 *(volatile ULONG
* const)Register
= Value
;
445 KeFlushWriteBuffer();
450 WRITE_REGISTER_USHORT(IN PUSHORT Register
,
453 *(volatile USHORT
* const)Register
= Value
;
454 KeFlushWriteBuffer();