X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fio-layer%2Fatomic.h;h=c9ead6aeadf21b0faf08aeb49bb0e3f3b37f58b2;hb=484afa344023a34e5b48e168aab76bdb33f80765;hp=8fff350ab987067aabd15a2541e83046bb89d8fc;hpb=c76dfadc4ab7416a0345e99f00b42bc73021c1ae;p=mono.git diff --git a/mono/io-layer/atomic.h b/mono/io-layer/atomic.h index 8fff350ab98..c9ead6aeadf 100644 --- a/mono/io-layer/atomic.h +++ b/mono/io-layer/atomic.h @@ -10,11 +10,61 @@ #ifndef _WAPI_ATOMIC_H_ #define _WAPI_ATOMIC_H_ +#if defined(__NetBSD__) +#include + +#if __NetBSD_Version__ > 499004000 +#include +#define HAVE_ATOMIC_OPS +#endif + +#endif + #include #include "mono/io-layer/wapi.h" -#if defined(__i386__) || defined(__x86_64__) +#if defined(__NetBSD__) && defined(HAVE_ATOMIC_OPS) + +#define WAPI_ATOMIC_ASM +static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, + gint32 exch, gint32 comp) +{ + return atomic_cas_32((uint32_t*)dest, comp, exch); +} + +static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp) +{ + return atomic_cas_ptr(dest, comp, exch); +} + +static inline gint32 InterlockedIncrement(volatile gint32 *val) +{ + return atomic_inc_32_nv((uint32_t*)val); +} + +static inline gint32 InterlockedDecrement(volatile gint32 *val) +{ + return atomic_dec_32_nv((uint32_t*)val); +} + +static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val) +{ + return atomic_swap_32((uint32_t*)val, new_val); +} + +static inline gpointer InterlockedExchangePointer(volatile gpointer *val, + gpointer new_val) +{ + return atomic_swap_ptr(val, new_val); +} + +static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add) +{ + return atomic_add_32_nv((uint32_t*)val, add) - add; +} + +#elif defined(__i386__) || defined(__x86_64__) #define WAPI_ATOMIC_ASM /* @@ -301,7 +351,7 @@ InterlockedCompareExchange(volatile gint32 *dest, __asm__ __volatile__ ("\tLA\t1,%0\n" "\tLR\t%1,%3\n" "\tCS\t%1,%2,0(1)\n" - : "+m" (*dest), "=r" (old) + : "+m" (*dest), "=&r" (old) : "r" (exch), "r" (comp) : "1", "cc"); return(old); @@ -317,7 +367,7 @@ InterlockedCompareExchangePointer(volatile gpointer *dest, __asm__ __volatile__ ("\tLA\t1,%0\n" "\tLR\t%1,%3\n" "\tCS\t%1,%2,0(1)\n" - : "+m" (*dest), "=r" (old) + : "+m" (*dest), "=&r" (old) : "r" (exch), "r" (comp) : "1", "cc"); return(old); @@ -333,7 +383,7 @@ InterlockedCompareExchangePointer(volatile gpointer *dest, __asm__ __volatile__ ("\tLA\t1,%0\n" "\tLGR\t%1,%3\n" "\tCSG\t%1,%2,0(1)\n" - : "+m" (*dest), "=r" (old) + : "+m" (*dest), "=&r" (old) : "r" (exch), "r" (comp) : "1", "cc"); @@ -426,7 +476,7 @@ InterlockedExchange(volatile gint32 *val, gint32 new_val) "0:\tL\t%1,%0\n" "\tCS\t%1,%2,0(1)\n" "\tJNZ\t0b" - : "+m" (*val), "=r" (ret) + : "+m" (*val), "=&r" (ret) : "r" (new_val) : "1", "cc"); @@ -443,7 +493,7 @@ InterlockedExchangePointer(volatile gpointer *val, gpointer new_val) "0:\tL\t%1,%0\n" "\tCS\t%1,%2,0(1)\n" "\tJNZ\t0b" - : "+m" (*val), "=r" (ret) + : "+m" (*val), "=&r" (ret) : "r" (new_val) : "1", "cc"); @@ -459,7 +509,7 @@ InterlockedExchangePointer(volatile gpointer *val, gpointer new_val) "0:\tLG\t%1,%0\n" "\tCSG\t%1,%2,0(1)\n" "\tJNZ\t0b" - : "+m" (*val), "=r" (ret) + : "+m" (*val), "=&r" (ret) : "r" (new_val) : "1", "cc"); @@ -479,7 +529,7 @@ InterlockedExchangeAdd(volatile gint32 *val, gint32 add) "\tAR\t1,%2\n" "\tCS\t%0,1,0(2)\n" "\tJNZ\t0b" - : "=r" (ret), "+m" (*val) + : "=&r" (ret), "+m" (*val) : "r" (add) : "1", "2", "cc"); @@ -497,7 +547,7 @@ InterlockedExchangeAdd(volatile gint32 *val, gint32 add) "\tAGR\t1,%2\n" "\tCS\t%0,1,0(2)\n" "\tJNZ\t0b" - : "=r" (ret), "+m" (*val) + : "=&r" (ret), "+m" (*val) : "r" (add) : "1", "2", "cc"); @@ -505,9 +555,90 @@ InterlockedExchangeAdd(volatile gint32 *val, gint32 add) } # endif -#elif defined(__ppc__) || defined (__powerpc__) +#elif defined(__mono_ppc__) #define WAPI_ATOMIC_ASM +#ifdef G_COMPILER_CODEWARRIOR +static inline gint32 InterlockedIncrement(volatile register gint32 *val) +{ + gint32 result = 0, tmp; + register gint32 result = 0; + register gint32 tmp; + + asm + { + @1: + lwarx tmp, 0, val + addi result, tmp, 1 + stwcx. result, 0, val + bne- @1 + } + + return result; +} + +static inline gint32 InterlockedDecrement(register volatile gint32 *val) +{ + register gint32 result = 0; + register gint32 tmp; + + asm + { + @1: + lwarx tmp, 0, val + addi result, tmp, -1 + stwcx. result, 0, val + bne- @1 + } + + return result; +} +#define InterlockedCompareExchangePointer(dest,exch,comp) (void*)InterlockedCompareExchange((volatile gint32 *)(dest), (gint32)(exch), (gint32)(comp)) + +static inline gint32 InterlockedCompareExchange(volatile register gint32 *dest, register gint32 exch, register gint32 comp) +{ + register gint32 tmp = 0; + + asm + { + @1: + lwarx tmp, 0, dest + cmpw tmp, comp + bne- @2 + stwcx. exch, 0, dest + bne- @1 + @2: + } + + return tmp; +} +static inline gint32 InterlockedExchange(register volatile gint32 *dest, register gint32 exch) +{ + register gint32 tmp = 0; + + asm + { + @1: + lwarx tmp, 0, dest + stwcx. exch, 0, dest + bne- @1 + } + + return tmp; +} +#define InterlockedExchangePointer(dest,exch) (void*)InterlockedExchange((volatile gint32 *)(dest), (gint32)(exch)) +#else + +#ifdef __mono_ppc64__ +#define LDREGX "ldarx" +#define STREGCXD "stdcx." +#define CMPREG "cmpd" +#else +#define LDREGX "lwarx" +#define STREGCXD "stwcx." +#define CMPREG "cmpw" +#endif + static inline gint32 InterlockedIncrement(volatile gint32 *val) { gint32 result = 0, tmp; @@ -534,7 +665,22 @@ static inline gint32 InterlockedDecrement(volatile gint32 *val) return result - 1; } -#define InterlockedCompareExchangePointer(dest,exch,comp) InterlockedCompareExchange((volatile gint32 *)(dest), (gint32)(exch), (gint32)(comp)) +static inline gpointer InterlockedCompareExchangePointer (volatile gpointer *dest, + gpointer exch, gpointer comp) +{ + gpointer tmp = NULL; + + __asm__ __volatile__ ("\n1:\n\t" + LDREGX " %0, 0, %1\n\t" + CMPREG " %0, %2\n\t" + "bne- 2f\n\t" + STREGCXD " %3, 0, %1\n\t" + "bne- 1b\n" + "2:" + : "=&r" (tmp) + : "b" (dest), "r" (comp), "r" (exch): "cc", "memory"); + return(tmp); +} static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp) { @@ -563,7 +709,18 @@ static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch) : "=r" (tmp) : "0" (tmp), "b" (dest), "r" (exch): "cc", "memory"); return(tmp); } -#define InterlockedExchangePointer(dest,exch) InterlockedExchange((volatile gint32 *)(dest), (gint32)(exch)) + +static inline gpointer InterlockedExchangePointer (volatile gpointer *dest, gpointer exch) +{ + gpointer tmp = NULL; + + __asm__ __volatile__ ("\n1:\n\t" + LDREGX " %0, 0, %2\n\t" + STREGCXD " %3, 0, %2\n\t" + "bne 1b" + : "=r" (tmp) : "0" (tmp), "b" (dest), "r" (exch): "cc", "memory"); + return(tmp); +} static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add) { @@ -578,6 +735,12 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add) return(result); } +#undef LDREGX +#undef STREGCXD +#undef CMPREG + +#endif /* !G_COMPILER_CODEWARRIOR */ + #elif defined(__arm__) #define WAPI_ATOMIC_ASM @@ -710,13 +873,16 @@ static inline gint32 InterlockedCompareExchange(gint32 volatile *dest, gint32 exch, gint32 comp) { gint32 old; + guint64 real_comp; #ifdef __INTEL_COMPILER old = _InterlockedCompareExchange (dest, exch, comp); #else + /* cmpxchg4 zero extends the value read from memory */ + real_comp = (guint64)(guint32)comp; asm volatile ("mov ar.ccv = %2 ;;\n\t" "cmpxchg4.acq %0 = [%1], %3, ar.ccv\n\t" - : "=r" (old) : "r" (dest), "r" (comp), "r" (exch)); + : "=r" (old) : "r" (dest), "r" (real_comp), "r" (exch)); #endif return(old); @@ -1016,7 +1182,7 @@ extern gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch); extern gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch); extern gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add); -#if defined(__hpux) && !defined(__GNUC__) +#if defined(__hppa__) #define WAPI_ATOMIC_ASM #endif