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
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
22 #undef ExInterlockedAddLargeStatistic
24 /* FUNCTIONS ******************************************************************/
28 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
29 IN PSLIST_ENTRY ListEntry
)
32 PSINGLE_LIST_ENTRY FirstEntry
, NextEntry
;
33 PSINGLE_LIST_ENTRY Entry
= (PVOID
)ListEntry
, Head
= (PVOID
)ListHead
;
35 FirstEntry
= Head
->Next
;
38 Entry
->Next
= FirstEntry
;
39 NextEntry
= FirstEntry
;
40 FirstEntry
= (PVOID
)_InterlockedCompareExchange((PLONG
)Head
,
43 } while (FirstEntry
!= NextEntry
);
50 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
52 PSINGLE_LIST_ENTRY FirstEntry
, NextEntry
, Head
= (PVOID
)ListHead
;
54 FirstEntry
= Head
->Next
;
57 if (!FirstEntry
) return NULL
;
59 NextEntry
= FirstEntry
;
60 FirstEntry
= (PVOID
)_InterlockedCompareExchange((PLONG
)Head
,
61 (LONG
)FirstEntry
->Next
,
63 } while (FirstEntry
!= NextEntry
);
70 ExInterlockedFlushSList(IN PSLIST_HEADER ListHead
)
72 return (PVOID
)_InterlockedExchange((PLONG
)&ListHead
->Next
.Next
, (LONG
)NULL
);
77 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
78 IN PSLIST_ENTRY ListEntry
,
81 return InterlockedPushEntrySList(ListHead
, ListEntry
);
86 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
89 return InterlockedPopEntrySList(ListHead
);
94 ExfInterlockedAddUlong(IN PULONG Addend
,
99 KeAcquireSpinLock(Lock
, &OldIrql
);
100 *Addend
+= Increment
;
101 KeReleaseSpinLock(Lock
, OldIrql
);
107 ExfInterlockedCompareExchange64(IN OUT LONGLONG
volatile *Destination
,
108 IN PLONGLONG Exchange
,
109 IN PLONGLONG Comparand
)
113 Result
= *Destination
;
114 if (*Destination
== *Comparand
) *Destination
= *Exchange
;
120 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
121 IN PLIST_ENTRY ListEntry
,
125 PLIST_ENTRY OldHead
= NULL
;
126 KeAcquireSpinLock(Lock
, &OldIrql
);
127 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
128 InsertHeadList(ListHead
, ListEntry
);
129 KeReleaseSpinLock(Lock
, OldIrql
);
135 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
136 IN PLIST_ENTRY ListEntry
,
140 PLIST_ENTRY OldHead
= NULL
;
141 KeAcquireSpinLock(Lock
, &OldIrql
);
142 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
143 InsertTailList(ListHead
, ListEntry
);
144 KeReleaseSpinLock(Lock
, OldIrql
);
150 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
159 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
160 IN PSINGLE_LIST_ENTRY ListEntry
,
169 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
172 return ExInterlockedRemoveHeadList(ListHead
, Lock
);
177 ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend
,
178 IN LARGE_INTEGER Increment
,
181 LARGE_INTEGER Integer
= {{0}};
188 ExInterlockedAddUlong(IN PULONG Addend
,
192 return (ULONG
)_InterlockedExchangeAdd((PLONG
)Addend
, Increment
);
197 ExInterlockedIncrementLong(IN PLONG Addend
,
200 return _InterlockedIncrement(Addend
);
205 ExInterlockedDecrementLong(IN PLONG Addend
,
208 return _InterlockedDecrement(Addend
);
213 ExInterlockedExchangeUlong(IN PULONG Target
,
217 return (ULONG
)_InterlockedExchange((PLONG
)Target
, Value
);
222 ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
223 IN PLIST_ENTRY ListEntry
,
227 PLIST_ENTRY OldHead
= NULL
;
228 KeAcquireSpinLock(Lock
, &OldIrql
);
229 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
230 InsertHeadList(ListHead
, ListEntry
);
231 KeReleaseSpinLock(Lock
, OldIrql
);
237 ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
238 IN PLIST_ENTRY ListEntry
,
242 PLIST_ENTRY OldHead
= NULL
;
243 KeAcquireSpinLock(Lock
, &OldIrql
);
244 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
245 InsertTailList(ListHead
, ListEntry
);
246 KeReleaseSpinLock(Lock
, OldIrql
);
252 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
256 PSINGLE_LIST_ENTRY OldHead
= NULL
;
257 KeAcquireSpinLock(Lock
, &OldIrql
);
258 OldHead
= PopEntryList(ListHead
);
259 KeReleaseSpinLock(Lock
, OldIrql
);
265 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
266 IN PSINGLE_LIST_ENTRY ListEntry
,
270 PSINGLE_LIST_ENTRY OldHead
= NULL
;
271 KeAcquireSpinLock(Lock
, &OldIrql
);
272 OldHead
= ListHead
->Next
;
273 PushEntryList(ListHead
, ListEntry
);
274 KeReleaseSpinLock(Lock
, OldIrql
);
280 ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
284 PLIST_ENTRY OldHead
= NULL
;
285 KeAcquireSpinLock(Lock
, &OldIrql
);
286 if (!IsListEmpty(ListHead
)) OldHead
= RemoveHeadList(ListHead
);
287 KeReleaseSpinLock(Lock
, OldIrql
);
293 ExInterlockedAddLargeStatistic(IN PLONGLONG Addend
,
301 ExInterlockedCompareExchange64(IN OUT LONGLONG
volatile *Destination
,
302 IN PLONGLONG Exchange
,
303 IN PLONGLONG Comparand
,
309 KeAcquireSpinLock(Lock
, &OldIrql
);
310 Result
= *Destination
;
311 if (*Destination
== *Comparand
) *Destination
= *Exchange
;
312 KeReleaseSpinLock(Lock
, OldIrql
);
318 READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
322 PUCHAR registerBuffer
= Register
;
323 PUCHAR readBuffer
= Buffer
;
326 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
328 *readBuffer
= *(volatile UCHAR
* const)registerBuffer
;
334 READ_REGISTER_BUFFER_ULONG(IN PULONG Register
,
338 PULONG registerBuffer
= Register
;
339 PULONG readBuffer
= Buffer
;
342 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
344 *readBuffer
= *(volatile ULONG
* const)registerBuffer
;
350 READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
354 PUSHORT registerBuffer
= Register
;
355 PUSHORT readBuffer
= Buffer
;
358 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
360 *readBuffer
= *(volatile USHORT
* const)registerBuffer
;
366 READ_REGISTER_UCHAR(IN PUCHAR Register
)
368 return *(volatile UCHAR
* const)Register
;
373 READ_REGISTER_ULONG(IN PULONG Register
)
375 return *(volatile ULONG
* const)Register
;
380 READ_REGISTER_USHORT(IN PUSHORT Register
)
382 return *(volatile USHORT
* const)Register
;
387 WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
391 PUCHAR registerBuffer
= Register
;
392 PUCHAR writeBuffer
= Buffer
;
394 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
396 *(volatile UCHAR
* const)registerBuffer
= *writeBuffer
;
398 KeFlushWriteBuffer();
403 WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register
,
407 PULONG registerBuffer
= Register
;
408 PULONG writeBuffer
= Buffer
;
410 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
412 *(volatile ULONG
* const)registerBuffer
= *writeBuffer
;
414 KeFlushWriteBuffer();
419 WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
423 PUSHORT registerBuffer
= Register
;
424 PUSHORT writeBuffer
= Buffer
;
426 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
428 *(volatile USHORT
* const)registerBuffer
= *writeBuffer
;
430 KeFlushWriteBuffer();
435 WRITE_REGISTER_UCHAR(IN PUCHAR Register
,
438 *(volatile UCHAR
* const)Register
= Value
;
439 KeFlushWriteBuffer();
444 WRITE_REGISTER_ULONG(IN PULONG Register
,
447 *(volatile ULONG
* const)Register
= Value
;
448 KeFlushWriteBuffer();
453 WRITE_REGISTER_USHORT(IN PUSHORT Register
,
456 *(volatile USHORT
* const)Register
= Value
;
457 KeFlushWriteBuffer();