X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fatomic.c;h=9ab8746f299f98ca783767ec8545aea0bab17928;hb=09747fb182d51c5c8963d68325204964c6b845f2;hp=585ffd6cfca977deb7fafc7546aee9c6bcea7070;hpb=a33ce0c39fe7aa04292eb2fa2d0c89da7ba02c6e;p=mono.git diff --git a/mono/utils/atomic.c b/mono/utils/atomic.c old mode 100755 new mode 100644 index 585ffd6cfca..9ab8746f299 --- a/mono/utils/atomic.c +++ b/mono/utils/atomic.c @@ -12,32 +12,26 @@ #include #include +#include #if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC) #include -static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t spin G_GNUC_UNUSED = PTHREAD_MUTEX_INITIALIZER; + +#define NEED_64BIT_CMPXCHG_FALLBACK #endif #ifdef WAPI_NO_ATOMIC_ASM -static mono_once_t spin_once=MONO_ONCE_INIT; - -static void spin_init(void) -{ - g_warning("Using non-atomic functions! Expect race conditions when using process-shared handles!"); -} - gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp) { gint32 old; int ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); ret = pthread_mutex_lock(&spin); @@ -62,8 +56,6 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer old; int ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); ret = pthread_mutex_lock(&spin); @@ -82,13 +74,53 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, return(old); } +gint32 InterlockedAdd(volatile gint32 *dest, gint32 add) +{ + gint32 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dest += add; + ret= *dest; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + +gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add) +{ + gint64 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dest += add; + ret= *dest; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + gint32 InterlockedIncrement(volatile gint32 *dest) { gint32 ret; int thr_ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -105,13 +137,32 @@ gint32 InterlockedIncrement(volatile gint32 *dest) return(ret); } +gint64 InterlockedIncrement64(volatile gint64 *dest) +{ + gint64 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + (*dest)++; + ret= *dest; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + gint32 InterlockedDecrement(volatile gint32 *dest) { gint32 ret; int thr_ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -128,13 +179,32 @@ gint32 InterlockedDecrement(volatile gint32 *dest) return(ret); } +gint64 InterlockedDecrement64(volatile gint64 *dest) +{ + gint64 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + (*dest)--; + ret= *dest; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch) { gint32 ret; int thr_ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -151,13 +221,32 @@ gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch) return(ret); } +gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch) +{ + gint64 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + ret=*dest; + *dest=exch; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch) { gpointer ret; int thr_ret; - mono_once(&spin_once, spin_init); - pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); thr_ret = pthread_mutex_lock(&spin); @@ -179,7 +268,26 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add) gint32 ret; int thr_ret; - mono_once(&spin_once, spin_init); + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + ret= *dest; + *dest+=add; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + +gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add) +{ + gint64 ret; + int thr_ret; pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&spin); @@ -197,72 +305,237 @@ gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add) return(ret); } -#define NEED_64BIT_CMPXCHG_FALLBACK +gint8 InterlockedRead8(volatile gint8 *src) +{ + gint8 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); -#endif + ret= *src; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); -#if defined (BROKEN_64BIT_ATOMICS_INTRINSIC) + pthread_cleanup_pop (0); -#if defined (TARGET_MACH) && defined (__arm__) && defined (HAVE_ARMV7) + return(ret); +} -gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) __attribute__ ((naked)); +gint16 InterlockedRead16(volatile gint16 *src) +{ + gint16 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); -gint64 -InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) + ret= *src; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + +gint32 InterlockedRead(volatile gint32 *src) { - __asm__ ( - "push {r4, r5, r6, r7}\n" - "ldr r4, [sp, #16]\n" - "dmb\n" -"1:\n" - "ldrexd r6, r7, [r0]\n" - "cmp r7, r4\n" - "bne 2f\n" - "cmp r6, r3\n" - "bne 2f\n" - "strexd r5, r1, r2, [r0]\n" - "cmp r5, #0\n" - "bne 1b\n" -"2:\n" - "dmb\n" - "mov r0, r6\n" - "mov r1, r7\n" - "pop {r4, r5, r6, r7}\n" - "bx lr\n" - ); + gint32 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + ret= *src; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); } -#elif defined (TARGET_MACH) && (defined (__i386__) || defined (__x86_64__)) +gint64 InterlockedRead64(volatile gint64 *src) +{ + gint64 ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); -gint64 -InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) + ret= *src; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); +} + +gpointer InterlockedReadPointer(volatile gpointer *src) { - return __sync_val_compare_and_swap (dest, comp, exch); + gpointer ret; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + ret= *src; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); + + return(ret); } -#else +void InterlockedWrite(volatile gint8 *dst, gint8 val) +{ + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); -#define NEED_64BIT_CMPXCHG_FALLBACK + *dst=val; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); +} -#endif +void InterlockedWrite16(volatile gint16 *dst, gint16 val) +{ + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dst=val; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); +} + +void InterlockedWrite(volatile gint32 *dst, gint32 val) +{ + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dst=val; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); +} + +void InterlockedWrite64(volatile gint64 *dst, gint64 val) +{ + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dst=val; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); +} + +void InterlockedWritePointer(volatile gpointer *dst, gpointer val) +{ + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + thr_ret = pthread_mutex_lock(&spin); + g_assert (thr_ret == 0); + + *dst=val; + + thr_ret = pthread_mutex_unlock(&spin); + g_assert (thr_ret == 0); + + pthread_cleanup_pop (0); +} #endif #if defined (NEED_64BIT_CMPXCHG_FALLBACK) +#if defined (TARGET_OSX) + +/* The compiler breaks if this code is in the header... */ + gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) { - gint64 old; + return __sync_val_compare_and_swap (dest, comp, exch); +} - pthread_mutex_lock (&spin); +#elif defined (HAVE_64BIT_CMPXCHG_FALLBACK) - old = *dest; - if(old == comp) - *dest = exch; +#ifdef ENABLE_EXTENSION_MODULE +#include "../../../mono-extensions/mono/utils/atomic.c" +#endif + +#else - pthread_mutex_unlock (&spin); - return old; +gint64 +InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) +{ + gint64 old; + int ret; + + pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, + (void *)&spin); + ret = pthread_mutex_lock(&spin); + g_assert (ret == 0); + + old= *dest; + if(old==comp) { + *dest=exch; + } + + ret = pthread_mutex_unlock(&spin); + g_assert (ret == 0); + + pthread_cleanup_pop (0); + + return(old); } #endif + +#endif