- Rewrite Executive Interlocked Functions to actually work as supposed and also immensly increase their speed, most notably on non-SMP machines:
  * The functions now disable interrupts as they should. This is a core functionality of the ExInterlocked functions which we did not do.
  * The functions now preserve EFLAGS as they should. This is another core functionality and point of ExInterlocked functions, which we did not do.
  * Use KiAcquire/ReleaseSpinlock equivalents instead of going through HAL. Also make them macros which can be later used in other assembly files.
  * Write optimized versions for non-SMP machines. Namely, the spinlock macros are coded to be no-ops on UP machines, since they are not needed.
  * Write all functions in assembly, so we can cleanly optimize them and properly restore/save EFLAGS and use CLI.
- Use the right interlocked macro in guarded mutex implementation.
- Fix export of Exi386InterlockedExchangeUlong
- Use documented EFLAGS definition instead of hard-coded value in some interlocked functions.
Modified: trunk/reactos/include/ndk/asm.h
Added: trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S
Modified: trunk/reactos/ntoskrnl/ex/i386/interlck_asm.S
Deleted: trunk/reactos/ntoskrnl/ex/interlck.c
Deleted: trunk/reactos/ntoskrnl/ex/list.c
Deleted: trunk/reactos/ntoskrnl/ex/synch.c
Modified: trunk/reactos/ntoskrnl/ke/gmutex.c
Modified: trunk/reactos/ntoskrnl/ntoskrnl.def
Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml

Modified: trunk/reactos/include/ndk/asm.h
--- trunk/reactos/include/ndk/asm.h	2005-12-30 23:50:05 UTC (rev 20473)
+++ trunk/reactos/include/ndk/asm.h	2005-12-30 23:53:13 UTC (rev 20474)
@@ -289,6 +289,9 @@
 #define EFLAGS_ALIGN_CHECK                      0x40000
 #define EFLAGS_VIF                              0x80000
 #define EFLAGS_VIP                              0x100000
+#define EFLAG_SIGN                              0x8000
+#define EFLAG_ZERO                              0x4000
+#define EFLAG_SELECT                            (EFLAG_SIGN | EFLAG_ZERO)
 
 //
 // CR0

Added: trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S
--- trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S	2005-12-30 23:50:05 UTC (rev 20473)
+++ trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S	2005-12-30 23:53:13 UTC (rev 20474)
@@ -0,0 +1,701 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ex/i386/fastinterlck_asm.S
+ * PURPOSE:         FASTCALL Interlocked Functions
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+ 
+/* INCLUDES ******************************************************************/
+#include <ndk/asm.h>
+.intel_syntax noprefix
+
+//#define CONFIG_SMP
+
+#ifdef CONFIG_SMP
+#define LOCK lock
+#define ACQUIRE_SPINLOCK(x, y) \
+    lock bts dword ptr [x], 0; \
+    jb y
+#define RELEASE_SPINLOCK(x) mov byte ptr [x], 0
+#define SPIN_ON_LOCK(x, y) \
+1: \
+    test dword ptr [x], 1; \
+    jz y; \
+    pause; \
+    jmp 1b
+#else
+#define LOCK
+#define ACQUIRE_SPINLOCK(x, y)
+#define RELEASE_SPINLOCK(x) 
+#endif
+
+/* FUNCTIONS ****************************************************************/
+
+/*
+ * NOTE: These functions must obey the following rules:
+ *  - Acquire locks only on MP systems.
+ *  - Be safe at HIGH_LEVEL (no paged access).
+ *  - Preserve flags.
+ *  - Disable interrups.
+ */
+
+/*VOID
+ *FASTCALL
+ *ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend,
+ *                               IN ULONG Increment)
+ */
+.global @ExInterlockedAddLargeStatistic@8
+@ExInterlockedAddLargeStatistic@8:
+
+#ifdef CONFIG_SMP
+    /* Do the addition */
+    lock add [ecx], edx
+
+    /* Check for carry bit and return */
+    jb 1f
+    ret
+
+1:
+    /* Add carry */
+    lock adc dword ptr [ecx+4], 0
+#else
+    /* Do the addition and add the carry */
+    add dword ptr [ecx], edx
+    adc dword ptr [ecx+4], 0
+#endif
+    /* Return */
+    ret
+
+/*ULONG
+ *FASTCALL
+ *ExfInterlockedAddUlong(IN PULONG Addend,
+ *                       IN ULONG Increment,
+ *                       IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedAddUlong@12
+@ExfInterlockedAddUlong@12:
+
+    /* Save flags */
+    pushfd
+
+#ifdef CONFIG_SMP
+    /* Get lock address */
+    mov eax, [esp+8]
+.start1:
+#endif
+    /* Disable interrupts */
+    cli
+
+    /* Acquire lock */
+    ACQUIRE_SPINLOCK(eax, .spin1)
+
+    /* Do the add */
+    mov eax, [ecx]
+    add [ecx], edx
+
+#ifdef CONFIG_SMP
+    /* Get spinlock address and release it */
+    mov edx, [esp+8]
+    RELEASE_SPINLOCK(edx)
+#endif
+
+    /* Restore flags and return */
+    popfd
+    ret 4
+
+#ifdef CONFIG_SMP
+.spin1:
+    /* Restore flags and spin */
+    popfd
+    pushfd
+    SPIN_ON_LOCK(eax, .start1)
+#endif
+
+/*PLIST_ENTRY
+ *FASTCALL
+ *ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
+ *                             IN PLIST_ENTRY ListEntry,
+ *                             IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedInsertHeadList@12
+@ExfInterlockedInsertHeadList@12:
+
+#ifdef CONFIG_SMP
+    /* Save lock address */
+    push esi
+    mov esi, [esp+8]
+#endif
+
+    /* Save flags and disable interrupts */
+    pushfd
+.start2:
+    cli
+
+    /* Acquire lock */
+    ACQUIRE_SPINLOCK(esi, .spin2)
+
+    /* Get list pointer */
+    mov eax, [ecx]
+
+    /* Do the insert */
+    mov [edx], eax
+    mov [edx+4], ecx
+    mov [ecx], edx
+    mov [eax+4], edx
+
+    /* Release lock and restore flags */
+    RELEASE_SPINLOCK(esi)
+    popfd
+
+#ifdef CONFIG_SMP
+    pop esi
+#endif
+
+    /* Check if list was empty */
+    xor eax, ecx
+    jz 2f
+
+    /* Return list pointer */
+    xor eax, ecx
+2:
+    ret 4
+
+#ifdef CONFIG_SMP
+.spin2:
+    popfd
+    pushfd
+    SPIN_ON_LOCK(esi, .start2)
+#endif
+
+/*PLIST_ENTRY
+ *NTAPI
+ *ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
+ *                            IN PLIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedInsertTailList@12
+@ExfInterlockedInsertTailList@12:
+
+#ifdef CONFIG_SMP
+    /* Save lock address */
+    push esi
+    mov esi, [esp+8]
+#endif
+
+    /* Save flags and disable interrupts */
+    pushfd
+.start3:
+    cli
+
+    /* Acquire lock */
+    ACQUIRE_SPINLOCK(esi, .spin3)
+
+    /* Get list pointer */
+    mov eax, [ecx+4]
+
+    /* Do the insert */
+    mov [edx], ecx
+    mov [edx+4], eax
+    mov [ecx+4], edx
+    mov [eax], edx
+
+    /* Release lock and restore flags */
+    RELEASE_SPINLOCK(esi)
+    popfd
+
+#ifdef CONFIG_SMP
+    pop esi
+#endif
+
+    /* Check if list was empty */
+    xor eax, ecx
+    jz 2f
+
+    /* Return list pointer */
+    xor eax, ecx
+2:
+    ret 4
+
+#ifdef CONFIG_SMP
+.spin3:
+    popfd
+    pushfd
+    SPIN_ON_LOCK(esi, .start3)
+#endif
+
+/*PLIST_ENTRY
+ *FASTCALL
+ *ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead,
+ *                             IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedRemoveHeadList@8
+@ExfInterlockedRemoveHeadList@8:
+
+    /* Save flags and disable interrupts */
+.start4:
+    pushfd
+    cli
+    ACQUIRE_SPINLOCK(edx, .spin4)
+
+    /* Get list pointer */
+    mov eax, [ecx]
+
+    /* Check if it's empty */
+    cmp eax, ecx
+    je 2f
+
+    /* Get the next entry and do the deletion*/
+#ifdef CONFIG_SMP
+    push ebx
+    mov ebx, [eax]
+    mov [ecx], ebx
+    mov [ebx+4], ecx
+#else
+    mov edx, [eax]
+    mov [ecx], edx
+    mov [edx+4], ecx
+#endif
+
+    /* Release lock */
+#ifdef CONFIG_SMP
+    RELEASE_SPINLOCK(edx)
+    pop ebx
+#endif
+
+    /* Restore flags */
+    popfd
+
+    /* Return */
+    ret
+
+2:
+    /* Release lock */
+    RELEASE_SPINLOCK(edx)
+
+    /* Restore flags */
+    popfd
+
+    /* Return empty list */
+    xor eax, eax
+    ret
+
+#ifdef CONFIG_SMP
+.spin4:
+    popfd
+    SPIN_ON_LOCK(edx, .start4)
+#endif
+
+/*PSINGLE_LIST_ENTRY
+ *FASTCALL
+ *ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+ *                          IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedPopEntryList@8
+@ExfInterlockedPopEntryList@8:
+
+    /* Save flags and disable interrupts */
+.start5:
+    pushfd
+    cli
+    ACQUIRE_SPINLOCK(edx, .spin5)
+
+    /* Get list pointer */
+    mov eax, [ecx]
+
+    /* Check if it's empty */
+    or eax, eax
+    je 3f
+
+    /* Get next entry and do deletion */
+#ifdef CONFIG_SMP
+    push edx
+#endif
+    mov edx, [eax]
+    mov [ecx], edx
+#ifdef CONFIG_SMP
+    pop edx
+#endif
+
+2:
+    /* Release lock */
+    RELEASE_SPINLOCK(edx)
+
+    /* Restore flags */
+    popfd
+
+    /* Return */
+    ret
+
+3:
+    /* Return empty list */
+    xor eax, eax
+    jmp 2b
+
+#ifdef CONFIG_SMP
+.spin5:
+    popfd
+    SPIN_ON_LOCK(edx, .start5)
+#endif
+
+/*PSINGLE_LIST_ENTRY
+ *NTAPI
+ *ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
+ *                            IN PSINGLE_LIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global @ExfInterlockedPushEntryList@12
+@ExfInterlockedPushEntryList@12:
+
+    /* Save flags */
+    pushfd
+
+    /* Save lock pointer */
+#ifdef CONFIG_SMP
+    push edx
+    mov edx, [esp+12]
+#endif
+
+    /* Disable interrupts */
+.start6:
+    cli
+#ifdef CONFIG_SMP
+    ACQUIRE_SPINLOCK(edx, .spin6)
+    pop edx
+#endif
+
+    /* Get list pointer */
+    mov eax, [ecx]
+
+    /* Do push */
+    mov [edx], eax
+    mov [ecx], edx
+
+    /* Release lock */
+#ifdef CONFIG_SMP
+    mov edx, [esp+8]
+    RELEASE_SPINLOCK(edx)
+#endif
+
+    /* Restore flags */
+    popfd
+
+    /* Return */
+    ret 4
+
+#ifdef CONFIG_SMP
+.spin6:
+    pop edx
+    popfd
+    pushfd
+    push edx
+    mov edx, [esp+12]
+    SPIN_ON_LOCK(edx, .start6)
+#endif
+
+/*PSINGLE_LIST_ENTRY
+ *NTAPI
+ *ExInterlockedPopEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
+ *                           IN PKSPIN_LOCK Lock)
+ */
+.global @ExInterlockedPopEntrySList@8
+.global @InterlockedPopEntrySList@4
+@ExInterlockedPopEntrySList@8:
+@InterlockedPopEntrySList@4:
+
+    /* Save registers */
+    push ebx
+    push ebp
+
+    /* Pointer to list */
+    mov ebp, ecx
+
+    /* Get sequence number and link pointer */
+    mov edx, [ebp+4]
+    mov eax, [ebp]
+
+1:
+    /* Check if the list is empty */
+    or eax, eax
+    jz 2f
+
+    /* Copy sequence number and adjust it */
+    lea ecx, [edx-1]
+
+    /* Get next pointer and do the exchange */
+    mov ebx, [eax]
+    LOCK cmpxchg8b qword ptr [ebp]
+    jnz 1b
+
+    /* Restore registers and return */
+2:
+    pop ebp
+    pop ebx
+    ret
+
+/*PSINGLE_LIST_ENTRY
+ *NTAPI
+ *ExInterlockedPushEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
+ *                            IN PSINGLE_LIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global @ExInterlockedPushEntrySList@12
+@ExInterlockedPushEntrySList@12:
+
+    /* So we can fall through below */
+    pop [esp]
+
+.global @InterlockedPushEntrySList@8
+@InterlockedPushEntrySList@8:
+
+    /* Save registers */
+    push ebx
+    push ebp
+
+    /* Pointer to list */
+    mov ebp, ecx
+    mov ebx, edx
+
+    /* Get sequence number and link pointer */
+    mov edx, [ebp+4]
+    mov eax, [ebp]
+
+1:
+    /* Set link pointer */
+    mov [ebx], eax
+
+    /* Copy sequence number and adjust it */
+    lea ecx, [edx+0x10001]
+
+    /* Do the exchange */
+    LOCK cmpxchg8b qword ptr [ebp]
+    jnz 1b
+
+    /* Restore registers and return */
+2:
+    pop ebp
+    pop ebx
+    ret
+
+/*PSINGLE_LIST_ENTRY
+ *NTAPI
+ *ExInterlockedFlushSList(IN PSINGLE_LIST_ENTRY ListHead)
+ */
+.global @ExInterlockedFlushSList@4
+@ExInterlockedFlushSList@4:
+
+    /* Save registers */
+    push ebx
+    push ebp
+
+    /* Clear ebx */
+    xor ebx, ebx
+
+    /* Pointer to list */
+    mov ebp, ecx
+
+    /* Get sequence number and link pointer */
+    mov edx, [ebp+4]
+    mov eax, [ebp]
+
+1:
+    /* Check if the list is empty */
+    or eax, eax
+    jz 2f
+
+    /* Clear sequence and pointer */
+    mov ecx, edx
+    mov cx, bx
+
+    /* Do the exchange */
+    LOCK cmpxchg8b qword ptr [ebp]
+    jnz 1b
+
+    /* Restore registers and return */
+2:
+    pop ebp
+    pop ebx
+    ret
+
+/*INTERLOCKED_RESULT
+ *FASTCALL
+ *Exfi386InterlockedIncrementLong(IN PLONG Addend)
+ */
+.global @Exfi386InterlockedIncrementLong@4
+@Exfi386InterlockedIncrementLong@4:
+
+    /* Do the op */
+    LOCK add dword ptr [ecx], 1
+
+    /* Return */
+    lahf
+    and eax, EFLAG_SELECT
+    ret
+
+/*INTERLOCKED_RESULT
+ *FASTCALL
+ *Exfi386InterlockedDecrementLong(IN PLONG Addend)
+ */
+.global @Exfi386InterlockedDecrementLong@4
+@Exfi386InterlockedDecrementLong@4:
+
+    /* Do the op */
+    LOCK sub dword ptr [ecx], 1
+
+    /* Return */
+    lahf
+    and eax, EFLAG_SELECT
+    ret
+
+/*ULONG
+ *FASTCALL
+ *Exfi386InterlockedExchangeUlong(IN PULONG Taget,
+ *                                IN ULONG Value)
+ */
+.global @Exfi386InterlockedExchangeUlong@8
+.global @InterlockedExchange@8
+@InterlockedExchange@8:
+@Exfi386InterlockedExchangeUlong@8:
+
+#ifdef CONFIG_SMP
+    /* On MP, do the exchange */
+    xchg [ecx], edx
+    mov eax, edx
+#else
+    /* On UP, use cmpxchg */
+    mov eax, [ecx]
+1:
+    cmpxchg [ecx], edx
+    jnz 1b
+#endif
+
+    /* Return */
+    ret
+
+/*ULONG
+ *FASTCALL
+ *InterlockedIncrement(IN PLONG Addend)
+ */
+.global @InterlockedIncrement@4
+@InterlockedIncrement@4:
+
+    /* Do the op */
+    mov eax, 1
+    LOCK xadd dword ptr [ecx], eax
+
+    /* Return */
+    inc eax
+    ret
+
+/*ULONG
+ *FASTCALL
+ *InterlockedDecrement(IN PLONG Addend)
+ */
+.global @InterlockedDecrement@4
+@InterlockedDecrement@4:
+
+    /* Do the op */
+    mov eax, -1
+    LOCK xadd dword ptr [ecx], eax
+
+    /* Return */
+    dec eax
+    ret
+
+/*PVOID
+ *FASTCALL
+ *InterlockedCompareExchange(IN OUT PVOID *Destination,
+ *                           IN PVOID Exchange,
+ *                           IN PVOID Comperand)
+ */
+.global @InterlockedCompareExchange@12
+@InterlockedCompareExchange@12:
+
+    /* Get comperand */
+    mov eax, [esp+4]
+
+    /* Do the op */
+    LOCK cmpxchg dword ptr [ecx], edx
+
+    /* Return */
+    ret
+
+/*PVOID
+ *FASTCALL
+ *ExfInterlockedCompareExchange64(IN PLONGLONG Destination,
+ *                                IN PLONGLONG Exchange,
+ *                                IN PLONGLONG Comperand)
+ */
+.global @ExfInterlockedCompareExchange64@12
+@ExfInterlockedCompareExchange64@12:
+
+    /* Save registers */
+    push ebp
+    push ebp
+
+    /* Get desination pointer, exchange value and comperand value/address */
+    mov ebp, ecx
+    mov ebx, [edx]
+    mov ecx, [edx+4]
+    mov edx, [esp+12]
+    mov eax, [edx]
+    mov edx, [edx+4]
+
+    /* Do the op */
+    LOCK cmpxchg8b qword ptr [ebp]
+
+    /* Restore volatiles */
+    pop ebp
+    pop ebx
+
+    /* Return */
+    ret 4
+
+/*PVOID
+ *FASTCALL
+ *ExfInterlockedCompareExchange64(IN PLONGLONG Destination,
+ *                                IN PLONGLONG Exchange,
+ *                                IN PLONGLONG Comperand,
+ *                                IN PKSPIN_LOCK Lock)
+ */
+.global @ExInterlockedCompareExchange64@16
+@ExInterlockedCompareExchange64@16:
+
+    /* Save registers */
+    push ebp
+    push ebp
+
+    /* Get desination pointer, exchange value and comperand value/address */
+    mov ebp, ecx
+    mov ebx, [edx]
+    mov ecx, [edx+4]
+    mov edx, [esp+12]
+    mov eax, [edx]
+    mov edx, [edx+4]
+
+    /* Do the op */
+    LOCK cmpxchg8b qword ptr [ebp]
+
+    /* Restore volatiles */
+    pop ebp
+    pop ebx
+
+    /* Return */
+    ret 8
+
+/*PVOID
+ *FASTCALL
+ *InterlockedExchangeAdd(IN OUT PLONG Addend,
+ *                       IN LONG Increment)
+ */
+.global @InterlockedExchangeAdd@8
+@InterlockedExchangeAdd@8:
+
+    /* Do the op */
+    LOCK xadd dword ptr [ecx], edx
+
+    /* Return */
+    mov eax, edx
+    ret
+
+/* EOF */

Modified: trunk/reactos/ntoskrnl/ex/i386/interlck_asm.S
--- trunk/reactos/ntoskrnl/ex/i386/interlck_asm.S	2005-12-30 23:50:05 UTC (rev 20473)
+++ trunk/reactos/ntoskrnl/ex/i386/interlck_asm.S	2005-12-30 23:53:13 UTC (rev 20474)
@@ -1,112 +1,583 @@
-/* $Id: interlck.c 15557 2005-05-28 07:26:38Z hbirr $
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ex/i386/interlck.c
- * PURPOSE:         No purpose listed.
- *
- * PROGRAMMERS:     No programmer listed.
+ * FILE:            ntoskrnl/ex/i386/interlck_asm.S
+ * PURPOSE:         STDCALL Interlocked Functions
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
+ 
+/* INCLUDES ******************************************************************/
+#include <ndk/asm.h>
+.intel_syntax noprefix
 
+//#define CONFIG_SMP
+
 #ifdef CONFIG_SMP
 #define LOCK lock
+#define ACQUIRE_SPINLOCK(x, y) \
+    lock bts dword ptr [x], 0; \
+    jb y
+#define RELEASE_SPINLOCK(x) mov byte ptr [x], 0
+#define SPIN_ON_LOCK(x, y) \
+1: \
+    test dword ptr [x], 1; \
+    jz y; \
+    pause; \
+    jmp 1b
 #else
 #define LOCK
+#define ACQUIRE_SPINLOCK(x, y)
+#define RELEASE_SPINLOCK(x) 
 #endif
 
-.global @Exfi386InterlockedIncrementLong@4
-@Exfi386InterlockedIncrementLong@4:
-	LOCK
-	addl $1,(%ecx)
-	lahf
-	andl $0xC000, %eax
-	ret
+/* FUNCTIONS ****************************************************************/
 
-.global @Exfi386InterlockedDecrementLong@4
-@Exfi386InterlockedDecrementLong@4:
-	LOCK
-	subl $1,(%ecx)
-	lahf
-	andl $0xC000, %eax
-	ret
+/*
+ * NOTE: These functions must obey the following rules:
+ *  - Acquire locks only on MP systems.
+ *  - Be safe at HIGH_LEVEL (no paged access).
+ *  - Preserve flags.
+ *  - Disable interrups.
+ */
 
-.global @Exfi386InterlockedExchangeUlong@8
-@Exfi386InterlockedExchangeUlong@8:
-	LOCK
-	xchgl %edx,(%ecx)
-	movl  %edx,%eax
-	ret
+/*PLIST_ENTRY
+ *NTAPI
+ *ExInterlockedAddLargeInteger(IN PLIST_ENTRY ListHead,
+ *                             IN PLIST_ENTRY ListEntry,
+ *                             IN PKSPIN_LOCK Lock)
+ */
+.global _ExInterlockedAddLargeInteger@16
+_ExInterlockedAddLargeInteger@16:
 
+    /* Prepare stack frame */
+    push ebp
+    mov ebp, esp
+    sub esp, 8
+
+    /* Save lock pointer */
+#ifdef CONFIG_SMP
+    mov eax, [ebp+20]
+#endif
+
+    /* Save flags and disable interrupts */
+.start1:
+    pushfd
+    cli
+
+    /* Acquire lock */
+    ACQUIRE_SPINLOCK(eax, .spin1)
+
+    /* Do the calculation */
+    mov eax, [ebp+8]
+    mov ecx, [eax]
+    mov edx, [eax+4]
+
+    /* Save result */
+    mov [ebp-8], ecx
+    mov [ebp-4], edx
+
+    /* Add increment */
+    add ecx, [ebp+12]
+    adc edx, [ebp+16]
+
+    /* Save result */
+    mov [eax], ecx
+    mov [eax+4], edx
+
+    /* Release lock */
+#ifdef CONFIG_SMP
+    mov eax, [ebp+20]
+    RELEASE_SPINLOCK(eax)
+#endif
+
+    /* Restore flags */
+    popfd
+
+    /* Restore frame and return values */
+    mov eax, [ebp-8]
+    mov edx, [ebp-4]
+    mov esp, ebp
+    pop ebp
+    ret 16
+
+#ifdef CONFIG_SMP
+.spin1:
+    popfd
+    SPIN_ON_LOCK(eax, .start1)
+#endif
+
+/*PLIST_ENTRY
+ *NTAPI
+ *ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
+ *                            IN PLIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global _ExInterlockedAddUlong@12
+_ExInterlockedAddUlong@12:
+
+    /* Save flags and disable interrupts */
+    pushfd
+
+    /* Get lock address */
+#ifdef CONFIG_SMP
+    mov edx, [ebp+16]
+#endif
+.start2:
+    cli
+
+    /* Acquire lock */
+    ACQUIRE_SPINLOCK(edx, .spin2)
+
+    /* Do the calculation */
+    mov ecx, [esp+8]
+#ifdef CONFIG_SMP
+    mov eax, [ecx]
+    add eax, [esp+12]
+
+    /* Save result */
+    mov [ecx], eax
+#else
+
+    /* Do the calculation */
+    mov edx, [ecx]
+    mov eax, edx
+    add edx, [esp+12]
+
+    /* Save result */
+    mov [ecx], edx
+#endif
+
+    /* Release lock, restore flags and return */
+#ifdef CONFIG_SMP
+    sub eax, [esp+12]
+    RELEASE_SPINLOCK(edx)
+#endif
+    popfd
+    ret 12
+
+#ifdef CONFIG_SMP
+.spin2:
+    popfd
+    pushfd
+    SPIN_ON_LOCK(eax, .start2)
+#endif
+
+/*PLIST_ENTRY
+ *NTAPI
+ *ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
+ *                            IN PLIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global _ExInterlockedInsertHeadList@12
+_ExInterlockedInsertHeadList@12:
+
+    /* Save lock pointer */
+#ifdef CONFIG_SMP
+    mov edx, [esp+12]
+#endif
+
+    /* Save flags and disable interrupts */
+.start3:
+    pushfd
+    cli
+    ACQUIRE_SPINLOCK(edx, .spin3)
+
+    /* Get list pointers */
+    mov eax, [esp+8]
+    mov ecx, [esp+12]
+    mov edx, [eax]
+
+    /* Do the insert */
+    mov [ecx], edx
+    mov [ecx+4], eax
+    mov [eax], ecx
+    mov [edx+4], ecx
+
+    /* Release lock */
+#ifdef CONFIG_SMP
+    mov ecx, [esp+16]
+    RELEASE_SPINLOCK(ecx)
+#endif
+
+    /* Restore flags */
+    popfd
+
+    /* check if the list was empty and return NULL */
+    xor eax, edx
+    jz 2f
+
+    /* Return pointer */
+    mov eax, edx
+
+2:
+    ret 12
+
+#ifdef CONFIG_SMP
+.spin3:
+    popfd
+    SPIN_ON_LOCK(edx, .start3)
+#endif
+
+/*PLIST_ENTRY
+ *NTAPI
+ *ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
+ *                            IN PLIST_ENTRY ListEntry,
+ *                            IN PKSPIN_LOCK Lock)
+ */
+.global _ExInterlockedInsertTailList@12
+_ExInterlockedInsertTailList@12:
+
+    /* Save lock pointer */
+#ifdef CONFIG_SMP
+    mov edx, [esp+12]
+#endif
+
+    /* Save flags and disable interrupts */
+.start4:
+    pushfd
+    cli
+    ACQUIRE_SPINLOCK(edx, .spin4)
+
+    /* Get list pointers */
+    mov eax, [esp+8]
+    mov ecx, [esp+12]
+    mov edx, [eax+4]
+
+    /* Do the insert */
+    mov [ecx], eax
+    mov [ecx+4], edx
+    mov [eax+4], ecx
[truncated at 1000 lines; 1285 more skipped]