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
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
,
80 return InterlockedPushEntrySList(ListHead
, ListEntry
);
85 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
88 return InterlockedPopEntrySList(ListHead
);
93 ExfInterlockedAddUlong(IN PULONG Addend
,
98 KeAcquireSpinLock(Lock
, &OldIrql
);
100 KeReleaseSpinLock(Lock
, OldIrql
);
106 ExfInterlockedCompareExchange64(IN OUT LONGLONG
volatile *Destination
,
107 IN PLONGLONG Exchange
,
108 IN PLONGLONG Comperand
)
112 Result
= *Destination
;
113 if (*Destination
== Result
) *Destination
= *Exchange
;
119 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
120 IN PLIST_ENTRY ListEntry
,
124 PLIST_ENTRY OldHead
= NULL
;
125 KeAcquireSpinLock(Lock
, &OldIrql
);
126 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
127 InsertHeadList(ListHead
, ListEntry
);
128 KeReleaseSpinLock(Lock
, OldIrql
);
134 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
135 IN PLIST_ENTRY ListEntry
,
139 PLIST_ENTRY OldHead
= NULL
;
140 KeAcquireSpinLock(Lock
, &OldIrql
);
141 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
142 InsertTailList(ListHead
, ListEntry
);
143 KeReleaseSpinLock(Lock
, OldIrql
);
149 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
158 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
159 IN PSINGLE_LIST_ENTRY ListEntry
,
168 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
171 return ExInterlockedRemoveHeadList(ListHead
, Lock
);
176 ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend
,
177 IN LARGE_INTEGER Increment
,
180 LARGE_INTEGER Integer
= {{0}};
187 ExInterlockedAddUlong(IN PULONG Addend
,
191 return (ULONG
)_InterlockedExchangeAdd((PLONG
)Addend
, Increment
);
196 ExInterlockedIncrementLong(IN PLONG Addend
,
199 return _InterlockedIncrement(Addend
);
204 ExInterlockedDecrementLong(IN PLONG Addend
,
207 return _InterlockedDecrement(Addend
);
212 ExInterlockedExchangeUlong(IN PULONG Target
,
216 return (ULONG
)_InterlockedExchange((PLONG
)Target
, Value
);
221 ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
222 IN PLIST_ENTRY ListEntry
,
226 PLIST_ENTRY OldHead
= NULL
;
227 KeAcquireSpinLock(Lock
, &OldIrql
);
228 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Flink
;
229 InsertHeadList(ListHead
, ListEntry
);
230 KeReleaseSpinLock(Lock
, OldIrql
);
236 ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
237 IN PLIST_ENTRY ListEntry
,
241 PLIST_ENTRY OldHead
= NULL
;
242 KeAcquireSpinLock(Lock
, &OldIrql
);
243 if (!IsListEmpty(ListHead
)) OldHead
= ListEntry
->Blink
;
244 InsertTailList(ListHead
, ListEntry
);
245 KeReleaseSpinLock(Lock
, OldIrql
);
251 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
255 PSINGLE_LIST_ENTRY OldHead
= NULL
;
256 KeAcquireSpinLock(Lock
, &OldIrql
);
257 if (!ListHead
->Next
) OldHead
= PopEntryList(ListHead
);
258 KeReleaseSpinLock(Lock
, OldIrql
);
264 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
265 IN PSINGLE_LIST_ENTRY ListEntry
,
269 PSINGLE_LIST_ENTRY OldHead
= NULL
;
270 KeAcquireSpinLock(Lock
, &OldIrql
);
271 if (!ListHead
->Next
) OldHead
= PushEntryList(ListHead
, ListEntry
);
272 KeReleaseSpinLock(Lock
, OldIrql
);
278 ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead
,
282 PLIST_ENTRY OldHead
= NULL
;
283 KeAcquireSpinLock(Lock
, &OldIrql
);
284 if (!IsListEmpty(ListHead
)) OldHead
= RemoveHeadList(ListHead
);
285 KeReleaseSpinLock(Lock
, OldIrql
);
291 ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend
,
299 ExInterlockedCompareExchange64(IN OUT PLONGLONG Destination
,
300 IN PLONGLONG Exchange
,
301 IN PLONGLONG Comparand
,
307 KeAcquireSpinLock(Lock
, &OldIrql
);
308 Result
= *Destination
;
309 if (*Destination
== Result
) *Destination
= *Exchange
;
310 KeReleaseSpinLock(Lock
, OldIrql
);
316 READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
320 PUCHAR registerBuffer
= Register
;
321 PUCHAR readBuffer
= Buffer
;
324 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
326 *readBuffer
= *(volatile UCHAR
* const)registerBuffer
;
332 READ_REGISTER_BUFFER_ULONG(IN PULONG Register
,
336 PULONG registerBuffer
= Register
;
337 PULONG readBuffer
= Buffer
;
340 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
342 *readBuffer
= *(volatile ULONG
* const)registerBuffer
;
348 READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
352 PUSHORT registerBuffer
= Register
;
353 PUSHORT readBuffer
= Buffer
;
356 for (readCount
= Count
; readCount
--; readBuffer
++, registerBuffer
++)
358 *readBuffer
= *(volatile USHORT
* const)registerBuffer
;
364 READ_REGISTER_UCHAR(IN PUCHAR Register
)
366 return *(volatile UCHAR
* const)Register
;
371 READ_REGISTER_ULONG(IN PULONG Register
)
373 return *(volatile ULONG
* const)Register
;
378 READ_REGISTER_USHORT(IN PUSHORT Register
)
380 return *(volatile USHORT
* const)Register
;
385 WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register
,
389 PUCHAR registerBuffer
= Register
;
390 PUCHAR writeBuffer
= Buffer
;
392 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
394 *(volatile UCHAR
* const)registerBuffer
= *writeBuffer
;
396 KeFlushWriteBuffer();
401 WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register
,
405 PULONG registerBuffer
= Register
;
406 PULONG writeBuffer
= Buffer
;
408 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
410 *(volatile ULONG
* const)registerBuffer
= *writeBuffer
;
412 KeFlushWriteBuffer();
417 WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register
,
421 PUSHORT registerBuffer
= Register
;
422 PUSHORT writeBuffer
= Buffer
;
424 for (writeCount
= Count
; writeCount
--; writeBuffer
++, registerBuffer
++)
426 *(volatile USHORT
* const)registerBuffer
= *writeBuffer
;
428 KeFlushWriteBuffer();
433 WRITE_REGISTER_UCHAR(IN PUCHAR Register
,
436 *(volatile UCHAR
* const)Register
= Value
;
437 KeFlushWriteBuffer();
442 WRITE_REGISTER_ULONG(IN PULONG Register
,
445 *(volatile ULONG
* const)Register
= Value
;
446 KeFlushWriteBuffer();
451 WRITE_REGISTER_USHORT(IN PUSHORT Register
,
454 *(volatile USHORT
* const)Register
= Value
;
455 KeFlushWriteBuffer();