2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/i386/fastinterlck_asm.S
5 * PURPOSE: FASTCALL Interlocked Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
11 .intel_syntax noprefix
17 #define ACQUIRE_SPINLOCK(x, y) \
18 lock bts dword ptr [x], 0; \
20 #define RELEASE_SPINLOCK(x) mov byte ptr [x], 0
21 #define SPIN_ON_LOCK(x, y) \
23 test dword ptr [x], 1; \
29 #define ACQUIRE_SPINLOCK(x, y)
30 #define RELEASE_SPINLOCK(x)
33 /* FUNCTIONS ****************************************************************/
36 * NOTE: These functions must obey the following rules:
37 * - Acquire locks only on MP systems.
38 * - Be safe at HIGH_LEVEL (no paged access).
40 * - Disable interrups.
45 *ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend,
48 .global @ExInterlockedAddLargeStatistic@8
49 @ExInterlockedAddLargeStatistic@8:
55 /* Check for carry bit and return */
61 lock adc dword ptr [ecx+4], 0
63 /* Do the addition and add the carry */
64 add dword ptr [ecx], edx
65 adc dword ptr [ecx+4], 0
72 *ExfInterlockedAddUlong(IN PULONG Addend,
74 * IN PKSPIN_LOCK Lock)
76 .global @ExfInterlockedAddUlong@12
77 @ExfInterlockedAddUlong@12:
83 /* Get lock address */
87 /* Disable interrupts */
91 ACQUIRE_SPINLOCK(eax, .spin1)
98 /* Get spinlock address and release it */
100 RELEASE_SPINLOCK(edx)
103 /* Restore flags and return */
109 /* Restore flags and spin */
112 SPIN_ON_LOCK(eax, .start1)
117 *ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
118 * IN PLIST_ENTRY ListEntry,
119 * IN PKSPIN_LOCK Lock)
121 .global @ExfInterlockedInsertHeadList@12
122 @ExfInterlockedInsertHeadList@12:
125 /* Save lock address */
130 /* Save flags and disable interrupts */
136 ACQUIRE_SPINLOCK(esi, .spin2)
138 /* Get list pointer */
147 /* Release lock and restore flags */
148 RELEASE_SPINLOCK(esi)
155 /* Check if list was empty */
159 /* Return list pointer */
168 SPIN_ON_LOCK(esi, .start2)
173 *ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
174 * IN PLIST_ENTRY ListEntry,
175 * IN PKSPIN_LOCK Lock)
177 .global @ExfInterlockedInsertTailList@12
178 @ExfInterlockedInsertTailList@12:
181 /* Save lock address */
186 /* Save flags and disable interrupts */
192 ACQUIRE_SPINLOCK(esi, .spin3)
194 /* Get list pointer */
203 /* Release lock and restore flags */
204 RELEASE_SPINLOCK(esi)
211 /* Check if list was empty */
215 /* Return list pointer */
224 SPIN_ON_LOCK(esi, .start3)
229 *ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead,
230 * IN PKSPIN_LOCK Lock)
232 .global @ExfInterlockedRemoveHeadList@8
233 @ExfInterlockedRemoveHeadList@8:
235 /* Save flags and disable interrupts */
239 ACQUIRE_SPINLOCK(edx, .spin4)
241 /* Get list pointer */
244 /* Check if it's empty */
248 /* Get the next entry and do the deletion*/
262 RELEASE_SPINLOCK(edx)
274 RELEASE_SPINLOCK(edx)
279 /* Return empty list */
286 SPIN_ON_LOCK(edx, .start4)
291 *ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
292 * IN PKSPIN_LOCK Lock)
294 .global @ExfInterlockedPopEntryList@8
295 @ExfInterlockedPopEntryList@8:
297 /* Save flags and disable interrupts */
301 ACQUIRE_SPINLOCK(edx, .spin5)
303 /* Get list pointer */
306 /* Check if it's empty */
310 /* Get next entry and do deletion */
322 RELEASE_SPINLOCK(edx)
331 /* Return empty list */
338 SPIN_ON_LOCK(edx, .start5)
343 *ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
344 * IN PSINGLE_LIST_ENTRY ListEntry,
345 * IN PKSPIN_LOCK Lock)
347 .global @ExfInterlockedPushEntryList@12
348 @ExfInterlockedPushEntryList@12:
353 /* Save lock pointer */
359 /* Disable interrupts */
363 ACQUIRE_SPINLOCK(edx, .spin6)
367 /* Get list pointer */
377 RELEASE_SPINLOCK(edx)
393 SPIN_ON_LOCK(edx, .start6)
398 *ExInterlockedPopEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
399 * IN PKSPIN_LOCK Lock)
401 .global @ExInterlockedPopEntrySList@8
402 .global @InterlockedPopEntrySList@4
403 @ExInterlockedPopEntrySList@8:
404 @InterlockedPopEntrySList@4:
410 /* Pointer to list */
413 /* Get sequence number and link pointer */
418 /* Check if the list is empty */
422 /* Copy sequence number and adjust it */
425 /* Get next pointer and do the exchange */
427 LOCK cmpxchg8b qword ptr [ebp]
430 /* Restore registers and return */
438 *ExInterlockedPushEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
439 * IN PSINGLE_LIST_ENTRY ListEntry,
440 * IN PKSPIN_LOCK Lock)
442 .global @ExInterlockedPushEntrySList@12
443 @ExInterlockedPushEntrySList@12:
445 /* So we can fall through below */
448 .global @InterlockedPushEntrySList@8
449 @InterlockedPushEntrySList@8:
455 /* Pointer to list */
459 /* Get sequence number and link pointer */
464 /* Set link pointer */
467 /* Copy sequence number and adjust it */
468 lea ecx, [edx+0x10001]
470 /* Do the exchange */
471 LOCK cmpxchg8b qword ptr [ebp]
474 /* Restore registers and return */
482 *ExInterlockedFlushSList(IN PSINGLE_LIST_ENTRY ListHead)
484 .global @ExInterlockedFlushSList@4
485 @ExInterlockedFlushSList@4:
494 /* Pointer to list */
497 /* Get sequence number and link pointer */
502 /* Check if the list is empty */
506 /* Clear sequence and pointer */
510 /* Do the exchange */
511 LOCK cmpxchg8b qword ptr [ebp]
514 /* Restore registers and return */
522 *Exfi386InterlockedIncrementLong(IN PLONG Addend)
524 .global @Exfi386InterlockedIncrementLong@4
525 @Exfi386InterlockedIncrementLong@4:
528 LOCK add dword ptr [ecx], 1
532 and eax, EFLAG_SELECT
537 *Exfi386InterlockedDecrementLong(IN PLONG Addend)
539 .global @Exfi386InterlockedDecrementLong@4
540 @Exfi386InterlockedDecrementLong@4:
543 LOCK sub dword ptr [ecx], 1
547 and eax, EFLAG_SELECT
552 *Exfi386InterlockedExchangeUlong(IN PULONG Taget,
555 .global @Exfi386InterlockedExchangeUlong@8
556 .global @InterlockedExchange@8
557 @InterlockedExchange@8:
558 @Exfi386InterlockedExchangeUlong@8:
561 /* On MP, do the exchange */
565 /* On UP, use cmpxchg */
577 *InterlockedIncrement(IN PLONG Addend)
579 .global @InterlockedIncrement@4
580 @InterlockedIncrement@4:
584 LOCK xadd dword ptr [ecx], eax
592 *InterlockedDecrement(IN PLONG Addend)
594 .global @InterlockedDecrement@4
595 @InterlockedDecrement@4:
599 LOCK xadd dword ptr [ecx], eax
607 *InterlockedCompareExchange(IN OUT PVOID *Destination,
609 * IN PVOID Comperand)
611 .global @InterlockedCompareExchange@12
612 @InterlockedCompareExchange@12:
618 LOCK cmpxchg dword ptr [ecx], edx
625 *ExfInterlockedCompareExchange64(IN PLONGLONG Destination,
626 * IN PLONGLONG Exchange,
627 * IN PLONGLONG Comperand)
629 .global @ExfInterlockedCompareExchange64@12
630 @ExfInterlockedCompareExchange64@12:
636 /* Get desination pointer, exchange value and comperand value/address */
645 LOCK cmpxchg8b qword ptr [ebp]
647 /* Restore volatiles */
656 *ExfInterlockedCompareExchange64(IN PLONGLONG Destination,
657 * IN PLONGLONG Exchange,
658 * IN PLONGLONG Comperand,
659 * IN PKSPIN_LOCK Lock)
661 .global @ExInterlockedCompareExchange64@16
662 @ExInterlockedCompareExchange64@16:
668 /* Get desination pointer, exchange value and comperand value/address */
677 LOCK cmpxchg8b qword ptr [ebp]
679 /* Restore volatiles */
688 *InterlockedExchangeAdd(IN OUT PLONG Addend,
691 .global @InterlockedExchangeAdd@8
692 @InterlockedExchangeAdd@8:
695 LOCK xadd dword ptr [ecx], edx