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