[NTOSKRNL]

Convert most ExInterlocked* functions from asm to C
Exceptions are ExInterlockedAddLargeStatistic and SList funcions

svn path=/trunk/; revision=52852
This commit is contained in:
Timo Kreuzer 2011-07-24 23:14:39 +00:00
parent d040534b02
commit dc06eeafec
4 changed files with 544 additions and 1191 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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 <asm.inc>
#include <ks386.inc>
#include <internal/i386/asmmacro.S>
/* 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 */

View file

@ -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 <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#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