2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/interlocked.c
5 * PURPOSE: Interlocked functions
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
9 /* INCLUDES *****************************************************************/
16 #undef ExInterlockedAddUlong
17 #undef ExInterlockedInsertHeadList
18 #undef ExInterlockedInsertTailList
19 #undef ExInterlockedRemoveHeadList
20 #undef ExInterlockedPopEntryList
21 #undef ExInterlockedPushEntryList
22 #undef ExInterlockedIncrementLong
23 #undef ExInterlockedDecrementLong
24 #undef ExInterlockedExchangeUlong
25 #undef ExInterlockedCompareExchange64
28 /* FUNCTIONS ****************************************************************/
32 _ExiDisableInteruptsAndAcquireSpinlock(
33 IN OUT PKSPIN_LOCK Lock
)
37 /* Disable interrupts */
38 Enabled
= KeDisableInterrupts();
40 /* Acquire the spinlock (inline) */
41 KxAcquireSpinLock(Lock
);
48 _ExiReleaseSpinLockAndRestoreInterupts(
49 IN OUT PKSPIN_LOCK Lock
,
52 /* Release the spinlock */
53 KxReleaseSpinLock(Lock
);
55 /* Restore interrupts */
56 KeRestoreInterrupts(Enable
);
62 ExInterlockedAddLargeInteger(
63 IN OUT PLARGE_INTEGER Addend
,
64 IN LARGE_INTEGER Increment
,
65 IN OUT PKSPIN_LOCK Lock
)
67 LARGE_INTEGER OldValue
;
70 /* Disable interrupts and acquire the spinlock */
71 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
73 /* Save the old value */
74 OldValue
.QuadPart
= Addend
->QuadPart
;
76 /* Do the operation */
77 Addend
->QuadPart
+= Increment
.QuadPart
;
79 /* Release the spinlock and restore interrupts */
80 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
82 /* Return the old value */
88 ExInterlockedAddUlong(
91 IN OUT PKSPIN_LOCK Lock
)
96 /* Disable interrupts and acquire the spinlock */
97 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
99 /* Save the old value */
102 /* Do the operation */
103 *Addend
+= Increment
;
105 /* Release the spinlock and restore interrupts */
106 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
108 /* Return the old value */
114 ExInterlockedInsertHeadList(
115 IN OUT PLIST_ENTRY ListHead
,
116 IN OUT PLIST_ENTRY ListEntry
,
117 IN OUT PKSPIN_LOCK Lock
)
120 PLIST_ENTRY FirstEntry
;
122 /* Disable interrupts and acquire the spinlock */
123 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
125 /* Save the first entry */
126 FirstEntry
= ListHead
->Flink
;
128 /* Insert the new entry */
129 InsertHeadList(ListHead
, ListEntry
);
131 /* Release the spinlock and restore interrupts */
132 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
134 /* Return the old first entry or NULL for empty list */
135 return (FirstEntry
== ListHead
) ? NULL
: FirstEntry
;
140 ExInterlockedInsertTailList(
141 IN OUT PLIST_ENTRY ListHead
,
142 IN OUT PLIST_ENTRY ListEntry
,
143 IN OUT PKSPIN_LOCK Lock
)
146 PLIST_ENTRY LastEntry
;
148 /* Disable interrupts and acquire the spinlock */
149 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
151 /* Save the last entry */
152 LastEntry
= ListHead
->Blink
;
154 /* Insert the new entry */
155 InsertTailList(ListHead
, ListEntry
);
157 /* Release the spinlock and restore interrupts */
158 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
160 /* Return the old last entry or NULL for empty list */
161 return (LastEntry
== ListHead
) ? NULL
: LastEntry
;
166 ExInterlockedRemoveHeadList(
167 IN OUT PLIST_ENTRY ListHead
,
168 IN OUT PKSPIN_LOCK Lock
)
171 PLIST_ENTRY ListEntry
;
173 /* Disable interrupts and acquire the spinlock */
174 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
176 /* Check if the list is empty */
177 if (IsListEmpty(ListHead
))
184 /* Remove the first entry from the list head */
185 ListEntry
= RemoveHeadList(ListHead
);
187 ListEntry
->Flink
= (PLIST_ENTRY
)0xBADDD0FF;
188 ListEntry
->Blink
= (PLIST_ENTRY
)0xBADDD0FF;
192 /* Release the spinlock and restore interrupts */
193 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
195 /* Return the entry */
201 ExInterlockedPopEntryList(
202 IN OUT PSINGLE_LIST_ENTRY ListHead
,
203 IN OUT PKSPIN_LOCK Lock
)
206 PSINGLE_LIST_ENTRY ListEntry
;
208 /* Disable interrupts and acquire the spinlock */
209 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
211 /* Pop the first entry from the list */
212 ListEntry
= PopEntryList(ListHead
);
215 ListEntry
->Next
= (PSINGLE_LIST_ENTRY
)0xBADDD0FF;
218 /* Release the spinlock and restore interrupts */
219 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
221 /* Return the entry */
227 ExInterlockedPushEntryList(
228 IN OUT PSINGLE_LIST_ENTRY ListHead
,
229 IN OUT PSINGLE_LIST_ENTRY ListEntry
,
230 IN OUT PKSPIN_LOCK Lock
)
233 PSINGLE_LIST_ENTRY OldListEntry
;
235 /* Disable interrupts and acquire the spinlock */
236 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
238 /* Save the old top entry */
239 OldListEntry
= ListHead
->Next
;
241 /* Push a new entry on the list */
242 PushEntryList(ListHead
, ListEntry
);
244 /* Release the spinlock and restore interrupts */
245 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
247 /* Return the entry */
253 ExInterlockedIncrementLong(
259 Result
= _InterlockedIncrement(Addend
);
260 return (Result
< 0) ? ResultNegative
:
261 (Result
> 0) ? ResultPositive
:
267 ExInterlockedDecrementLong(
273 Result
= _InterlockedDecrement(Addend
);
274 return (Result
< 0) ? ResultNegative
:
275 (Result
> 0) ? ResultPositive
:
281 ExInterlockedExchangeUlong(
286 return (ULONG
)_InterlockedExchange((PLONG
)Target
, (LONG
)Value
);
293 ExfInterlockedAddUlong(
294 IN OUT PULONG Addend
,
296 IN OUT PKSPIN_LOCK Lock
)
301 /* Disable interrupts and acquire the spinlock */
302 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
304 /* Save the old value */
307 /* Do the operation */
308 *Addend
+= Increment
;
310 /* Release the spinlock and restore interrupts */
311 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
313 /* Return the old value */
319 ExfInterlockedInsertHeadList(
320 IN OUT PLIST_ENTRY ListHead
,
321 IN PLIST_ENTRY ListEntry
,
322 IN OUT PKSPIN_LOCK Lock
)
325 PLIST_ENTRY FirstEntry
;
327 /* Disable interrupts and acquire the spinlock */
328 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
330 /* Save the first entry */
331 FirstEntry
= ListHead
->Flink
;
333 /* Insert the new entry */
334 InsertHeadList(ListHead
, ListEntry
);
336 /* Release the spinlock and restore interrupts */
337 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
339 /* Return the old first entry or NULL for empty list */
340 return (FirstEntry
== ListHead
) ? NULL
: FirstEntry
;
345 ExfInterlockedInsertTailList(
346 IN OUT PLIST_ENTRY ListHead
,
347 IN PLIST_ENTRY ListEntry
,
348 IN OUT PKSPIN_LOCK Lock
)
351 PLIST_ENTRY LastEntry
;
353 /* Disable interrupts and acquire the spinlock */
354 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
356 /* Save the last entry */
357 LastEntry
= ListHead
->Blink
;
359 /* Insert the new entry */
360 InsertTailList(ListHead
, ListEntry
);
362 /* Release the spinlock and restore interrupts */
363 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
365 /* Return the old last entry or NULL for empty list */
366 return (LastEntry
== ListHead
) ? NULL
: LastEntry
;
372 ExfInterlockedRemoveHeadList(
373 IN OUT PLIST_ENTRY ListHead
,
374 IN OUT PKSPIN_LOCK Lock
)
377 PLIST_ENTRY ListEntry
;
379 /* Disable interrupts and acquire the spinlock */
380 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
382 /* Check if the list is empty */
383 if (IsListEmpty(ListHead
))
390 /* Remove the first entry from the list head */
391 ListEntry
= RemoveHeadList(ListHead
);
393 ListEntry
->Flink
= (PLIST_ENTRY
)0x0BADD0FF;
394 ListEntry
->Blink
= (PLIST_ENTRY
)0x0BADD0FF;
398 /* Release the spinlock and restore interrupts */
399 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
401 /* return the entry */
407 ExfInterlockedPopEntryList(
408 IN OUT PSINGLE_LIST_ENTRY ListHead
,
409 IN OUT PKSPIN_LOCK Lock
)
412 PSINGLE_LIST_ENTRY ListEntry
;
414 /* Disable interrupts and acquire the spinlock */
415 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
417 /* Pop the first entry from the list */
418 ListEntry
= PopEntryList(ListHead
);
421 ListEntry
->Next
= (PSINGLE_LIST_ENTRY
)0xBADDD0FF;
424 /* Release the spinlock and restore interrupts */
425 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
427 /* return the entry */
433 ExfInterlockedPushEntryList(
434 IN OUT PSINGLE_LIST_ENTRY ListHead
,
435 IN PSINGLE_LIST_ENTRY ListEntry
,
436 IN OUT PKSPIN_LOCK Lock
)
439 PSINGLE_LIST_ENTRY OldListEntry
;
441 /* Disable interrupts and acquire the spinlock */
442 Enable
= _ExiDisableInteruptsAndAcquireSpinlock(Lock
);
444 /* Save the old top entry */
445 OldListEntry
= ListHead
->Next
;
447 /* Push a new entry on the list */
448 PushEntryList(ListHead
, ListEntry
);
450 /* Release the spinlock and restore interrupts */
451 _ExiReleaseSpinLockAndRestoreInterupts(Lock
, Enable
);
453 /* return the entry */
459 Exi386InterlockedIncrementLong(
464 Result
= _InterlockedIncrement(Addend
);
465 return (Result
< 0) ? ResultNegative
:
466 (Result
> 0) ? ResultPositive
:
472 Exfi386InterlockedIncrementLong(
473 IN OUT LONG
volatile *Addend
)
477 Result
= _InterlockedIncrement(Addend
);
478 return (Result
< 0) ? ResultNegative
:
479 (Result
> 0) ? ResultPositive
:
485 Exi386InterlockedDecrementLong(
490 Result
= _InterlockedDecrement(Addend
);
491 return (Result
< 0) ? ResultNegative
:
492 (Result
> 0) ? ResultPositive
:
498 Exfi386InterlockedDecrementLong(
503 Result
= _InterlockedDecrement(Addend
);
504 return (Result
< 0) ? ResultNegative
:
505 (Result
> 0) ? ResultPositive
:
511 Exi386InterlockedExchangeUlong(
515 return _InterlockedExchange(Target
, Exchange
);
520 Exfi386InterlockedExchangeUlong(
521 IN OUT PULONG Target
,
524 return _InterlockedExchange((PLONG
)Target
, Exchange
);
529 ExInterlockedCompareExchange64(
530 IN OUT LONGLONG
volatile *Destination
,
531 IN PLONGLONG Exchange
,
532 IN PLONGLONG Comparand
,
535 return _InterlockedCompareExchange64(Destination
, *Exchange
, *Comparand
);
540 ExfInterlockedCompareExchange64(
541 IN OUT LONGLONG
volatile *Destination
,
542 IN PLONGLONG Exchange
,
543 IN PLONGLONG Comparand
)
545 return _InterlockedCompareExchange64(Destination
, *Exchange
, *Comparand
);
553 ExInterlockedAddLargeStatistic(
554 IN OUT PLARGE_INTEGER Addend
,