/*- * Copyright 2005-2007 Guram Dukashvili * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //--------------------------------------------------------------------------- #ifndef _atomic_H_ #define _atomic_H_ //--------------------------------------------------------------------------- namespace ksys { //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- //#if __i386__ || __x86_64__ //#define FAST_MUTEX 1 //#endif //--------------------------------------------------------------------------- /*#ifndef MPLOCKED #ifdef SMP #define __STRING(x) #x #define __XSTRING(x) __STRING(x) #else #define __STRING(x) #x #define __XSTRING(x) __STRING(x) #endif #endif #define MPLOCKED2 "lock ; " //__XSTRING(MPLOCKED2)*/ //--------------------------------------------------------------------------- #if __GNUG__ && __i386__ //inline int32_t interlockedIncrement(volatile int32_t * v,int32_t a) //{ // asm volatile ( // " lock ; " // " xaddl %0, %1 ; " // "# atomic_fetchadd_int" // : "+r" (a), /* 0 (result) */ // "=m" (*v) /* 1 */ // : "m" (*v)); /* 2 */ // return a; //} #if !HAVE_ATOMIC_FETCHADD_32 static __inline uint32_t atomic_fetchadd_32(volatile uint32_t * p,uint32_t v) { __asm __volatile ( " lock ; " " xaddl %0, %1 ; " "# atomic_fetchadd_int" : "+r" (v), /* 0 (result) */ "=m" (*p) /* 1 */ : "m" (*p)); /* 2 */ return (v); } #endif inline int32_t interlockedIncrement(volatile int32_t & v,int32_t a) { asm volatile ( "lock; xadd %%eax,(%%edx)" : "=a" (a) : "d" (&v), "a" (a)); return a; /* // register long eax asm("eax"); // long r; __asm __volatile (// ".arch i686\n" // ".intel_syntax noprefix\n" __XSTRING(MPLOCKED) "xadd %%eax,(%%edx)\n" // возвращаемые параметры : "=a" (a) // принимаемые параметры : "d" (&v), // первый параметр %0 c - edx "a" (a) // второй параметр %1 a - eax // регистры, в которые гадим // : "ecx" );*/ // return interlockedIncrement(&v,a); //#if HAVE_ATOMIC_FETCHADD_32 return atomic_fetchadd_32((volatile uint32_t *) &v,a); //#else // asm volatile ( "lock; xadd %%eax,(%%edx)" : "=a" (a) : "d" (&v), "a" (a)); // return a; //#endif } int64_t interlockedIncrement(volatile int64_t & v,int64_t a); inline int32_t interlockedCompareExchange(volatile int32_t & v, int32_t exValue, int32_t cmpValue) { asm volatile ("lock; cmpxchg %%ecx,(%%edx)" : "=a" (cmpValue) : "d" (&v), "a" (cmpValue), "c" (exValue)); return cmpValue; } inline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue) { // asm volatile ("lock; cmpxchg8b (%%ebp)" : "=a" (cmpValue) : "ebp" (&v), "a" (cmpValue), "c" (exValue)); //#if HAVE_MACHINE_ATOMIC_H // atomic_cmpset_long(&v,cmpValue,exValue); //#endif // return cmpValue; return interlockedCompareExchange(*(int32_t *) &v,int32_t(exValue),int32_t(cmpValue)); } #elif __GNUG__ && __x86_64__ inline int32_t interlockedIncrement(volatile int32_t & v, int32_t a) { asm volatile ("lock; xadd %%eax,(%%rdx)" : "=a" (a) : "d" (&v), "a" (a)); return a; } inline int64_t interlockedIncrement(volatile int64_t & v,int64_t a) { asm volatile ("lock; xadd %%rax,(%%rdx)" : "=a" (a) : "d" (&v), "a" (a)); return a; } inline int32_t interlockedCompareExchange(volatile int32_t & v, int32_t exValue, int32_t cmpValue) { asm volatile ("lock; cmpxchg %%ecx,(%%rdx)" : "=a" (cmpValue) : "d" (&v), "a" (cmpValue), "c" (exValue)); return cmpValue; } inline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue) { asm volatile ("lock; cmpxchg %%rcx,(%%rdx)" : "=a" (cmpValue) : "d" (&v), "a" (cmpValue), "c" (exValue)); return cmpValue; } #elif _MSC_VER && _M_IX86 __forceinline int32_t __fastcall interlockedIncrement(volatile int32_t & v,int32_t a) { __asm { mov eax,a mov edx,v lock xadd [edx],eax } } int64_t interlockedIncrement(volatile int64_t & v,int64_t a); __forceinline int32_t interlockedCompareExchange(volatile int32_t & v,int32_t exValue,int32_t cmpValue) { __asm { mov eax,cmpValue mov ecx,exValue mov edx,v lock cmpxchg [edx],ecx } } __forceinline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue) { __asm { mov esi,v mov ebx,dword ptr exValue mov ecx,dword ptr exValue + 4 mov eax,dword ptr cmpValue mov edx,dword ptr cmpValue + 4 lock cmpxchg8b qword ptr [esi] } } #elif _MSC_VER && _M_X64 __forceinline int32_t interlockedIncrement(volatile int32_t & v,int32_t a) { return InterlockedExchangeAdd((LONG *) &v,a); } __forceinline int64_t interlockedIncrement(volatile int64_t & v,int64_t a) { return InterlockedExchangeAdd64((LONGLONG *) &v,a); } __forceinline int32_t interlockedCompareExchange(volatile int32_t & v, int32_t exValue, int32_t cmpValue) { return InterlockedCompareExchange((LONG *) &v,exValue,cmpValue); } __forceinline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue) { return InterlockedCompareExchange64((LONGLONG *) &v,exValue,cmpValue); } #elif defined(__BCPLUSPLUS__) int32_t __fastcall __declspec(nothrow) interlockedIncrement(int32_t & v,int32_t a); int32_t __fastcall __declspec(nothrow) interlockedCompareExchange(int32_t & v,int32_t exValue,int32_t cmpValue); #else int32_t interlockedIncrement(volatile int32_t & v, int32_t a); int32_t interlockedCompareExchange(volatile int32_t & v, int32_t exValue, int32_t cmpValue); #endif //--------------------------------------------------------------------------- void interlockedCompareExchangeAcquire(volatile int32_t & v,int32_t exValue,int32_t cmpValue); void interlockedCompareExchangeAcquire(volatile int64_t & v,int64_t exValue,int64_t cmpValue); inline uint32_t interlockedIncrement(volatile uint32_t & v,uint32_t a){ return interlockedIncrement(*(int32_t *) &v,(int32_t) a); } inline uint64_t interlockedIncrement(volatile uint64_t & v,uint64_t a){ return interlockedIncrement(*(int64_t *) &v,(int64_t) a); } #if SIZEOF_VOID_P <= 4 #if !HAVE_INTPTR_T_AS_INT32_T && !HAVE_INT32_T_AS_INTPTR_T inline uintptr_t interlockedIncrement(volatile intptr_t & v,intptr_t a){ return interlockedIncrement(*(int32_t *) &v,(int32_t) a); } inline uintptr_t interlockedIncrement(volatile uintptr_t & v,uintptr_t a){ return interlockedIncrement(*(int32_t *) &v,(int32_t) a); } #endif typedef int32_t ilock_t; typedef uint32_t uilock_t; #elif SIZEOF_VOID_P <= 8 #if !HAVE_INTPTR_T_AS_INT64_T && !HAVE_INT64_T_AS_INTPTR_T inline uintptr_t interlockedIncrement(volatile intptr_t & v,intptr_t a){ return interlockedIncrement(*(int64_t *) &v,(int64_t) a); } inline uintptr_t interlockedIncrement(volatile uintptr_t & v,uintptr_t a){ return interlockedIncrement(*(int64_t *) &v,(int64_t) a); } #endif typedef int64_t ilock_t; typedef uint64_t uilock_t; #endif //--------------------------------------------------------------------------- } // namespace ksys //--------------------------------------------------------------------------- #endif /* _atomic_H_ */ //---------------------------------------------------------------------------