mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 07:08:19 +00:00
565 lines
10 KiB
ArmAsm
565 lines
10 KiB
ArmAsm
/*
|
|
* 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 <reactos/asm.h>
|
|
#include <ndk/asm.h>
|
|
#include <internal/i386/asmmacro.S>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
.code32
|
|
.text
|
|
|
|
/*
|
|
* 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 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
|
|
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 2f
|
|
|
|
/* Return pointer */
|
|
mov eax, edx
|
|
|
|
2:
|
|
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)
|
|
*/
|
|
.global _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 2f
|
|
|
|
/* 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
|
|
|
|
2:
|
|
/* 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)
|
|
*/
|
|
.global _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 3f
|
|
|
|
/* Get next entry and do deletion */
|
|
mov edx, [eax]
|
|
mov [ecx], edx
|
|
|
|
2:
|
|
/* Release lock */
|
|
#ifdef CONFIG_SMP
|
|
mov ecx, [esp+12]
|
|
RELEASE_SPINLOCK(edx)
|
|
#endif
|
|
|
|
/* Restore flags */
|
|
popfd
|
|
|
|
/* Return */
|
|
ret 8
|
|
|
|
3:
|
|
/* Return empty list */
|
|
xor eax, eax
|
|
jmp 2b
|
|
|
|
#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)
|
|
*/
|
|
.global _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)
|
|
*/
|
|
.global _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)
|
|
*/
|
|
.global _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)
|
|
*/
|
|
.global _ExInterlockedExchangeUlong@12
|
|
_ExInterlockedExchangeUlong@12:
|
|
|
|
/* Get pointers */
|
|
mov edx, [esp+4]
|
|
mov eax, [esp+8]
|
|
|
|
#ifdef CONFIG_SMP
|
|
/* On MP, do the exchange */
|
|
xchg [edx], eax
|
|
#else
|
|
/* 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,
|
|
* IN PKSPIN_LOCK Lock)
|
|
*/
|
|
.global _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,
|
|
* IN PKSPIN_LOCK Lock)
|
|
*/
|
|
.global _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 8
|
|
|
|
/*ULONG
|
|
*NTAPI
|
|
*Exi386InterlockedExchangeUlong(IN PULONG Target,
|
|
* IN ULONG Value,
|
|
* IN PKSPIN_LOCK Lock)
|
|
*/
|
|
.global _Exi386InterlockedExchangeUlong@12
|
|
_Exi386InterlockedExchangeUlong@12:
|
|
|
|
/* Get pointers */
|
|
mov edx, [esp+4]
|
|
mov eax, [esp+8]
|
|
|
|
#ifdef CONFIG_SMP
|
|
/* On MP, do the exchange */
|
|
xchg [edx], eax
|
|
#else
|
|
/* On UP, disable interrupts and save flags */
|
|
pushfd
|
|
cli
|
|
|
|
/* Switch values */
|
|
mov eax, [edx]
|
|
mov [edx], ecx
|
|
popfd
|
|
#endif
|
|
|
|
/* Return */
|
|
ret 8
|
|
|
|
/* EOF */
|