From dc06eeafec034eb9d0699bc4920f84437c5db039 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 24 Jul 2011 23:14:39 +0000 Subject: [PATCH] [NTOSKRNL] Convert most ExInterlocked* functions from asm to C Exceptions are ExInterlockedAddLargeStatistic and SList funcions svn path=/trunk/; revision=52852 --- reactos/ntoskrnl/CMakeLists.txt | 2 +- reactos/ntoskrnl/ex/i386/fastinterlck_asm.S | 622 +------------------- reactos/ntoskrnl/ex/i386/interlck_asm.S | 569 ------------------ reactos/ntoskrnl/ex/i386/interlocked.c | 542 +++++++++++++++++ 4 files changed, 544 insertions(+), 1191 deletions(-) delete mode 100644 reactos/ntoskrnl/ex/i386/interlck_asm.S create mode 100644 reactos/ntoskrnl/ex/i386/interlocked.c diff --git a/reactos/ntoskrnl/CMakeLists.txt b/reactos/ntoskrnl/CMakeLists.txt index 2640133433b..84c5778f89c 100644 --- a/reactos/ntoskrnl/CMakeLists.txt +++ b/reactos/ntoskrnl/CMakeLists.txt @@ -276,8 +276,8 @@ list(APPEND SOURCE if(ARCH MATCHES i386) list(APPEND SOURCE config/i386/cmhardwr.c - ex/i386/interlck_asm.S ex/i386/fastinterlck_asm.S + ex/i386/interlocked.c ex/i386/ioport.S ke/i386/abios.c ke/i386/cpu.c diff --git a/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S b/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S index 43b832788f2..8de4260ab87 100644 --- a/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S +++ b/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S @@ -5,7 +5,7 @@ * PURPOSE: FASTCALL Interlocked Functions * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ - + /* INCLUDES ******************************************************************/ #include @@ -51,331 +51,7 @@ PUBLIC @ExInterlockedAddLargeStatistic@8 /* Return */ ret -/*ULONG - *FASTCALL - *ExfInterlockedAddUlong(IN PULONG Addend, - * IN ULONG Increment, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @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) - */ -PUBLIC @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 .l2 - - /* Return list pointer */ - xor eax, ecx -.l2: - ret 4 - -#ifdef CONFIG_SMP -.spin2: - popfd - pushfd - SPIN_ON_LOCK(esi, .start2) -#endif - -/*PLIST_ENTRY - *FASTCALL - *ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @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 .l3 - - /* Return list pointer */ - xor eax, ecx -.l3: - 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) - */ -PUBLIC @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 .l4 - - /* 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 - -.l4: - /* 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) - */ -PUBLIC @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 .l6 - - /* Get next entry and do deletion */ -#ifdef CONFIG_SMP - push edx -#endif - mov edx, [eax] - mov [ecx], edx -#ifdef CONFIG_SMP - pop edx -#endif - -.l5: - /* Release lock */ - RELEASE_SPINLOCK(edx) - - /* Restore flags */ - popfd - - /* Return */ - ret - -.l6: - /* Return empty list */ - xor eax, eax - jmp .l5 - -#ifdef CONFIG_SMP -.spin5: - popfd - SPIN_ON_LOCK(edx, .start5) -#endif - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @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 *FASTCALL @@ -505,301 +181,5 @@ PUBLIC @ExInterlockedFlushSList@4 pop ebx ret -/*INTERLOCKED_RESULT - *FASTCALL - *Exfi386InterlockedIncrementLong(IN PLONG Addend) - */ -PUBLIC @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) - */ -PUBLIC @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 Target, - * IN ULONG Value) - */ -PUBLIC @Exfi386InterlockedExchangeUlong@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] -.l11: - cmpxchg [ecx], edx - jnz .l11 -#endif - - /* Return */ - ret - -/*PVOID - *FASTCALL - *ExfInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand) - */ -PUBLIC @ExfInterlockedCompareExchange64@12 -@ExfInterlockedCompareExchange64@12: - - /* Save registers */ - push ebx - push ebp - - /* Get destination 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 - *ExInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExInterlockedCompareExchange64@16 -@ExInterlockedCompareExchange64@16: - - /* Save registers */ - push ebx - push ebp - - /* Get destination 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 - -/*** Non-586 functions ***/ - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPopEntrySList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPopEntrySList@8 -@ExfInterlockedPopEntrySList@8: - - /* Save flags */ -.starta: - pushfd - - /* Disable interrupts */ - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(edx, .spina) - - /* Get the next link and check if it's empty */ - mov eax, [ecx] - or eax, eax - jz .l12 - - /* Get address of the next link and store it */ - push [eax] - pop [ecx] - - /* Decrement list depth */ - dec dword ptr [ecx+4] - -.l12: -#ifdef CONFIG_SMP - /* Release spinlock */ - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags and return */ - popfd - ret 0 - -#ifdef CONFIG_SMP -.spina: - /* Restore flags and spin */ - popfd - SPIN_ON_LOCK(edx, .starta) -#endif - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPushEntrySList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPushEntrySList@12 -@ExfInterlockedPushEntrySList@12: - - /* Save flags */ -.startb: - pushfd - - /* Disable interrupts */ - cli - - /* Acquire lock */ -#ifndef CONFIG_SMP - mov eax, [esp+8] - ACQUIRE_SPINLOCK(eax, .spinb) -#endif - - /* Get the next link and check if it's empty */ - push [ecx] - - /* Get address of the next link and store it */ - pop [edx] - mov [ecx], edx - - /* Increment list depth */ - inc dword ptr [ecx+4] - -#ifdef CONFIG_SMP - /* Release spinlock */ - RELEASE_SPINLOCK(eax) -#endif - - /* Restore flags and return */ - popfd - ret 4 - -#ifdef CONFIG_SMP -.spinb: - /* Restore flags and spin */ - popfd - SPIN_ON_LOCK(eax, .startb) -#endif - -/*PVOID - *FASTCALL - *ExpInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExpInterlockedCompareExchange64@16 -@ExpInterlockedCompareExchange64@16: - - /* Save registers */ - push ebp - push ebp - - /* Get destination 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] - -#ifdef CONFIG_SMP - /* Save ESI so we can store KSPINLOCK in it */ - push esi - - /* Save flags and lock, and disable interrupts */ - pushfd - mov esi, [esp+24] -.startc: - cli - - /* Acquire the spinlock */ - ACQUIRE_SPINLOCK(esi, .spinc) -#else - /* Save flags and disable interrupts */ - pushfd - cli -#endif - - /* Compare bottom */ - cmp eax, [ebp] - jne NoMatch - - /* Compare top */ - cmp edx, [ebp+4] - jne NoMatch - - /* Save new value */ - mov [ebp], ebx - mov [ebp+4], ecx - -AfterSave: -#ifdef CONFIG_SMP - /* Release lock, restore volatiles and flags */ - RELEASE_SPINLOCK(esi) - popfd - pop esi -#else - popfd -#endif - - /* Restore the other volatiles and return */ - pop ebp - pop ebx - - /* Return */ - ret 8 - -NoMatch: - /* Return the current value */ - mov eax, [ebp] - mov edx, [ebp+4] - jmp AfterSave - -#ifdef CONFIG_SMP -.spinc: - /* Restore flags and spin */ - popfd - pushfd - SPIN_ON_LOCK(esi, .startc) -#endif - END /* EOF */ diff --git a/reactos/ntoskrnl/ex/i386/interlck_asm.S b/reactos/ntoskrnl/ex/i386/interlck_asm.S deleted file mode 100644 index 1cac56b50a9..00000000000 --- a/reactos/ntoskrnl/ex/i386/interlck_asm.S +++ /dev/null @@ -1,569 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ex/i386/interlck_asm.S - * PURPOSE: STDCALL Interlocked Functions - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include -#include - -/* FUNCTIONS ****************************************************************/ - -.code32 - -/* - * 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. - */ - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend, - * IN LARGE_INTEGER Increment, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _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 - *ExInterlockedAddUlong(IN PULONG Addend, - * IN ULONG Increment, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _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) - */ -PUBLIC _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 .l2 - - /* Return pointer */ - mov eax, edx - -.l2: - 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) - */ -PUBLIC _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 - mov [edx], 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 .l3 - - /* Return pointer */ - mov eax, edx - -.l3: - ret 12 - -#ifdef CONFIG_SMP -.spin4: - popfd - SPIN_ON_LOCK(edx, .start4) -#endif - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedRemoveHeadList@8 -_ExInterlockedRemoveHeadList@8: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+8] -#endif - - /* Save flags and disable interrupts */ -.start5: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin5) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [edx] - - /* Check if it's empty */ - cmp eax, edx - je .l4 - - /* Get next entry and do deletion */ - mov ecx, [eax] - mov [edx], ecx - mov [ecx+4], edx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 8 - -.l4: - /* Release lock */ -#ifdef CONFIG_SMP - mov edx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return empty list */ - xor eax, eax - ret 8 - -#ifdef CONFIG_SMP -.spin5: - popfd - SPIN_ON_LOCK(edx, .start5) -#endif - -/*PSINGLE_LIST_ENTRY - *NTAPI - *ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedPopEntryList@8 -_ExInterlockedPopEntryList@8: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+8] -#endif - - /* Save flags and disable interrupts */ -.start6: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin6) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [ecx] - - /* Check if it's empty */ - or eax, eax - je .l6 - - /* Get next entry and do deletion */ - mov edx, [eax] - mov [ecx], edx - -.l5: - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 8 - -.l6: - /* Return empty list */ - xor eax, eax - jmp .l5 - -#ifdef CONFIG_SMP -.spin6: - popfd - SPIN_ON_LOCK(edx, .start6) -#endif - -/*PSINGLE_LIST_ENTRY - *NTAPI - *ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedPushEntryList@12 -_ExInterlockedPushEntryList@12: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+12] -#endif - - /* Save flags and disable interrupts */ -.start7: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin7) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [edx] - mov ecx, [esp+12] - - /* Do push */ - mov [ecx], eax - mov [edx], ecx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+16] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 12 - -#ifdef CONFIG_SMP -.spin7: - popfd - SPIN_ON_LOCK(edx, .start7) -#endif - -/*INTERLOCKED_RESULT - *NTAPI - *ExInterlockedIncrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedIncrementLong@8 -_ExInterlockedIncrementLong@8: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK add dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 8 - -/*INTERLOCKED_RESULT - *NTAPI - *ExInterlockedDecrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedDecrementLong@8 -_ExInterlockedDecrementLong@8: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK sub dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 8 - -/*ULONG - *NTAPI - *ExInterlockedExchangeUlong(IN PULONG Target, - * IN ULONG Value, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedExchangeUlong@12 -_ExInterlockedExchangeUlong@12: - -#ifdef CONFIG_SMP - /* Get pointers */ - mov edx, [esp+4] - mov eax, [esp+8] - - /* On MP, do the exchange */ - xchg [edx], eax -#else - /* Get pointers */ - mov edx, [esp+4] - mov ecx, [esp+8] - - /* On UP, disable interrupts and save flags */ - pushfd - cli - - /* Switch values */ - mov eax, [edx] - mov [edx], ecx - popfd -#endif - - /* Return */ - ret 12 - -/*INTERLOCKED_RESULT - *NTAPI - *Exi386InterlockedIncrementLong(IN PLONG Addend) - */ -PUBLIC _Exi386InterlockedIncrementLong@4 -_Exi386InterlockedIncrementLong@4: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK add dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 4 - -/*INTERLOCKED_RESULT - *NTAPI - *Exi386InterlockedDecrementLong(IN PLONG Addend) - */ -PUBLIC _Exi386InterlockedDecrementLong@4 -_Exi386InterlockedDecrementLong@4: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK sub dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 4 - -/*ULONG - *NTAPI - *Exi386InterlockedExchangeUlong(IN PULONG Target, - * IN ULONG Value) - */ -PUBLIC _Exi386InterlockedExchangeUlong@8 -_Exi386InterlockedExchangeUlong@8: - -#ifdef CONFIG_SMP - /* Get pointers */ - mov edx, [esp+4] - mov eax, [esp+8] - - /* On MP, do the exchange */ - xchg [edx], eax -#else - /* Get pointers */ - mov edx, [esp+4] - mov ecx, [esp+8] - - /* On UP, disable interrupts and save flags */ - pushfd - cli - - /* Switch values */ - mov eax, [edx] - mov [edx], ecx - popfd -#endif - - /* Return */ - ret 8 - -END -/* EOF */ diff --git a/reactos/ntoskrnl/ex/i386/interlocked.c b/reactos/ntoskrnl/ex/i386/interlocked.c new file mode 100644 index 00000000000..06a0ed74f70 --- /dev/null +++ b/reactos/ntoskrnl/ex/i386/interlocked.c @@ -0,0 +1,542 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/ex/interlocked.c +* PURPOSE: Interlocked functions +* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) +*/ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#undef ExInterlockedAddUlong +#undef ExInterlockedInsertHeadList +#undef ExInterlockedInsertTailList +#undef ExInterlockedRemoveHeadList +#undef ExInterlockedPopEntryList +#undef ExInterlockedPushEntryList +#undef ExInterlockedIncrementLong +#undef ExInterlockedDecrementLong +#undef ExInterlockedExchangeUlong +#undef ExInterlockedCompareExchange64 + + +/* FUNCTIONS ****************************************************************/ + +#if defined(_M_IX86 ) || defined(_M_AMD64) +FORCEINLINE +ULONG_PTR +_ExiDisableInteruptsAndAcquireSpinlock( + IN OUT PKSPIN_LOCK Lock) +{ + UINT_PTR EFlags; + + /* Save flags */ + EFlags = __readeflags(); + + /* Disable interrupts */ + _disable(); + + /* Acquire the spinlock (inline) */ + KxAcquireSpinLock(Lock); + + return EFlags; +} + +FORCEINLINE +VOID +_ExiReleaseSpinLockAndRestoreInterupts( + IN OUT PKSPIN_LOCK Lock, + ULONG_PTR EFlags) +{ + /* Release the spinlock */ + KxReleaseSpinLock(Lock); + + /* Restore flags */ + __writeeflags(EFlags); +} +#else +#error Unimplemented +#endif + +LARGE_INTEGER +NTAPI +ExInterlockedAddLargeInteger( + IN OUT PLARGE_INTEGER Addend, + IN LARGE_INTEGER Increment, + IN OUT PKSPIN_LOCK Lock) +{ + LARGE_INTEGER OldValue; + ULONG_PTR LockHandle; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue.QuadPart = Addend->QuadPart; + + /* Do the operation */ + Addend->QuadPart += Increment.QuadPart; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the old value */ + return OldValue; +} + +ULONG +NTAPI +ExInterlockedAddUlong( + IN OUT PULONG Addend, + IN ULONG Increment, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + ULONG OldValue; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue = *Addend; + + /* Do the operation */ + *Addend += Increment; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the old value */ + return OldValue; +} + +PLIST_ENTRY +NTAPI +ExInterlockedInsertHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY FirstEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the first entry */ + FirstEntry = ListHead->Flink; + + /* Insert the new entry */ + InsertHeadList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the first entry */ + return FirstEntry; +} + +PLIST_ENTRY +NTAPI +ExInterlockedInsertTailList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY LastEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the last entry */ + LastEntry = ListHead->Blink; + + /* Insert the new entry */ + InsertTailList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the last entry */ + return LastEntry; +} + +PLIST_ENTRY +NTAPI +ExInterlockedRemoveHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Remove the first entry from the list head */ + ListEntry = RemoveHeadList(ListHead); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +NTAPI +ExInterlockedPopEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PSINGLE_LIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Pop the first entry from the list */ + ListEntry = PopEntryList(ListHead); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +NTAPI +ExInterlockedPushEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PSINGLE_LIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PSINGLE_LIST_ENTRY OldListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old top entry */ + OldListEntry = ListHead->Next; + + /* Push a new entry on the list */ + PushEntryList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return OldListEntry; +} + +INTERLOCKED_RESULT +NTAPI +ExInterlockedIncrementLong( + IN PLONG Addend, + IN PKSPIN_LOCK Lock) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +NTAPI +ExInterlockedDecrementLong( + IN PLONG Addend, + IN PKSPIN_LOCK Lock) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +ULONG +NTAPI +ExInterlockedExchangeUlong( + IN PULONG Target, + IN ULONG Value, + IN PKSPIN_LOCK Lock) +{ + return (ULONG)_InterlockedExchange((PLONG)Target, (LONG)Value); +} + +#ifdef _M_IX86 + +ULONG +FASTCALL +ExfInterlockedAddUlong( + IN OUT PULONG Addend, + IN ULONG Increment, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + ULONG OldValue; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue = *Addend; + + /* Do the operation */ + *Addend += Increment; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the old value */ + return OldValue; +} + +PLIST_ENTRY +FASTCALL +ExfInterlockedInsertHeadList( + IN OUT PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY FirstEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the first entry */ + FirstEntry = ListHead->Flink; + + /* Insert the new entry */ + InsertHeadList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the first entry */ + return FirstEntry; +} + +PLIST_ENTRY +FASTCALL +ExfInterlockedInsertTailList( + IN OUT PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY LastEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the last entry */ + LastEntry = ListHead->Blink; + + /* Insert the new entry */ + InsertTailList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the last entry */ + return LastEntry; +} + + +PLIST_ENTRY +FASTCALL +ExfInterlockedRemoveHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PLIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Check if the list is empty */ + if (IsListEmpty(ListHead)) + { + /* Return NULL */ + ListEntry = NULL; + } + else + { + /* Remove the first entry from the list head */ + ListEntry = RemoveHeadList(ListHead); + } + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +FASTCALL +ExfInterlockedPopEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PSINGLE_LIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Pop the first entry from the list */ + ListEntry = PopEntryList(ListHead); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +FASTCALL +ExfInterlockedPushEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + ULONG_PTR LockHandle; + PSINGLE_LIST_ENTRY OldListEntry; + + /* Disable interrupts and acquire the spinlock */ + LockHandle = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old top entry */ + OldListEntry = ListHead->Next; + + /* Push a new entry on the list */ + PushEntryList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, LockHandle); + + /* return the entry */ + return OldListEntry; +} + +INTERLOCKED_RESULT +NTAPI +Exi386InterlockedIncrementLong( + IN PLONG Addend) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +FASTCALL +Exfi386InterlockedIncrementLong( + IN OUT LONG volatile *Addend) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +NTAPI +Exi386InterlockedDecrementLong( + IN PLONG Addend) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +FASTCALL +Exfi386InterlockedDecrementLong( + IN OUT PLONG Addend) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +LONG +NTAPI +Exi386InterlockedExchangeUlong( + PLONG Target, + LONG Exchange) +{ + return _InterlockedExchange(Target, Exchange); +} + +ULONG +FASTCALL +Exfi386InterlockedExchangeUlong( + IN OUT PULONG Target, + IN ULONG Exchange) +{ + return _InterlockedExchange((PLONG)Target, Exchange); +} + +LONGLONG +FASTCALL +ExInterlockedCompareExchange64( + IN OUT LONGLONG volatile *Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand, + IN PKSPIN_LOCK Lock) +{ + return _InterlockedCompareExchange64(Destination, *Exchange, *Comparand); +} + +LONGLONG +FASTCALL +ExfInterlockedCompareExchange64( + IN OUT LONGLONG volatile *Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand) +{ + return _InterlockedCompareExchange64(Destination, *Exchange, *Comparand); +} +#endif + +#if 0 + +VOID +FASTCALL +ExInterlockedAddLargeStatistic( + IN OUT PLARGE_INTEGER Addend, + IN ULONG Increment) +{ +} + + +#endif +