[Mono-dev] _wapi_sparc_lock
Zoltan Varga
vargaz at gmail.com
Sat Mar 25 06:30:23 EST 2006
Hi,
This looks ok to me. I will try to test it on sparc/solaris, then
check it in, if it works.
Zoltan
On 3/25/06, David S. Miller <davem at davemloft.net> wrote:
> From: "David S. Miller" <davem at davemloft.net>
> Date: Fri, 24 Mar 2006 17:15:00 -0800 (PST)
>
> > In any event, I can provide a patch to use the proper modern
> > atomic instructions. And I'll work on that while this thread
> > discussion occurs.
>
> As promised, patch is below.
>
> With this I'm down to 3 testcase failures on sparc-*-linux*, and
> from looking at them all 3 of them could very well be glibc or
> kernel issues on Sparc.
>
> I've choosen the conservative route to deal with the case of Solaris
> without gcc, falling back to the generic non-assembler pthread
> implementation.
>
> 2006-03-24 David S. Miller <davem at sunset.davemloft.net>
>
> * atomic.c (__wapi_sparc_lock): Delete
> * atomic.h sparc: Reimplement Interlocked* primitives using CAS/CASx
> when __GNUC__, else we will fall back to the generic pthread version.
>
> --- mono/io-layer/atomic.c.~1~ 2005-04-12 10:21:43.000000000 -0700
> +++ mono/io-layer/atomic.c 2006-03-24 17:21:51.000000000 -0800
> @@ -14,11 +14,7 @@
>
> #include "mono/io-layer/wapi.h"
>
> -#ifdef WAPI_ATOMIC_ASM
> -#if defined(sparc) || defined (__sparc__)
> -volatile unsigned char _wapi_sparc_lock;
> -#endif
> -#else
> +#ifndef WAPI_ATOMIC_ASM
>
> static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
> static mono_once_t spin_once=MONO_ONCE_INIT;
> --- mono/io-layer/atomic.h.~1~ 2006-01-03 19:39:23.000000000 -0800
> +++ mono/io-layer/atomic.h 2006-03-24 18:56:48.000000000 -0800
> @@ -127,152 +127,167 @@ static inline gint32 InterlockedExchange
> return(ret);
> }
>
> -#elif defined(sparc) || defined (__sparc__)
> +#elif (defined(sparc) || defined (__sparc__)) && defined(__GNUC__)
> #define WAPI_ATOMIC_ASM
>
> -#ifdef __GNUC__
> -#define BEGIN_SPIN(tmp,lock) \
> -__asm__ __volatile__("1: ldstub [%1],%0\n\t" \
> - " cmp %0, 0\n\t" \
> - " bne 1b\n\t" \
> - " nop" \
> - : "=&r" (tmp) \
> - : "r" (&lock) \
> - : "memory");
> -
> -#define END_SPIN(lock) \
> -__asm__ __volatile__("stb %%g0, [%0]" \
> - : /* no outputs */ \
> - : "r" (&lock)\
> - : "memory");
> -#else
> -static inline void begin_spin(volatile unsigned char *lock)
> -{
> - asm("1: ldstub [%i0], %l0");
> - asm("cmp %l0,0");
> - asm("bne 1b");
> - asm("nop");
> -}
> -#define BEGIN_SPIN(tmp,lock) begin_spin(&lock);
> -#define END_SPIN(lock) ((lock) = 0);
> -#endif
> -
> -extern volatile unsigned char _wapi_sparc_lock;
> -
> G_GNUC_UNUSED
> -static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp)
> +static inline gint32 InterlockedCompareExchange(volatile gint32 *_dest, gint32 _exch, gint32 _comp)
> {
> - int tmp;
> + register volatile gint32 *dest asm("g1") = _dest;
> + register gint32 comp asm("o4") = _comp;
> + register gint32 exch asm("o5") = _exch;
> gint32 old;
>
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> + __asm__ __volatile__(
> + /* cas [%%g1], %%o4, %%o5 */
> + ".word 0xdbe0500c"
> + : "=r" (old)
> + : "0" (exch), "r" (dest), "r" (comp)
> + : "memory");
>
> - old = *dest;
> - if (old==comp) {
> - *dest=exch;
> - }
> -
> - END_SPIN(_wapi_sparc_lock)
> -
> - return(old);
> + return old;
> }
>
> G_GNUC_UNUSED
> -static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp)
> +static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *_dest, gpointer _exch, gpointer _comp)
> {
> - int tmp;
> - gpointer old;
> -
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - old = *dest;
> - if (old==comp) {
> - *dest=exch;
> - }
> + register volatile gpointer *dest asm("g1") = _dest;
> + register gpointer comp asm("o4") = _comp;
> + register gpointer exch asm("o5") = _exch;
> + gpointer old;
>
> - END_SPIN(_wapi_sparc_lock)
> + __asm__ __volatile__(
> +#ifdef SPARCV9
> + /* casx [%%g1], %%o4, %%o5 */
> + ".word 0xdbf0500c"
> +#else
> + /* cas [%%g1], %%o4, %%o5 */
> + ".word 0xdbe0500c"
> +#endif
> + : "=r" (old)
> + : "0" (exch), "r" (dest), "r" (comp)
> + : "memory");
>
> - return(old);
> + return old;
> }
>
> G_GNUC_UNUSED
> -static inline gint32 InterlockedIncrement(volatile gint32 *dest)
> +static inline gint32 InterlockedIncrement(volatile gint32 *_dest)
> {
> - int tmp;
> - gint32 ret;
> -
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - (*dest)++;
> - ret = *dest;
> -
> - END_SPIN(_wapi_sparc_lock)
> + register volatile gint32 *dest asm("g1") = _dest;
> + register gint32 tmp asm("o4");
> + register gint32 ret asm("o5");
> +
> + __asm__ __volatile__(
> + "1: ld [%%g1], %%o4\n\t"
> + " add %%o4, 1, %%o5\n\t"
> + /* cas [%%g1], %%o4, %%o5 */
> + " .word 0xdbe0500c\n\t"
> + " cmp %%o4, %%o5\n\t"
> + " bne 1b\n\t"
> + " add %%o5, 1, %%o5"
> + : "=&r" (tmp), "=&r" (ret)
> + : "r" (dest)
> + : "memory");
>
> - return(ret);
> + return ret;
> }
>
> G_GNUC_UNUSED
> -static inline gint32 InterlockedDecrement(volatile gint32 *dest)
> +static inline gint32 InterlockedDecrement(volatile gint32 *_dest)
> {
> - int tmp;
> - gint32 ret;
> -
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - (*dest)--;
> - ret = *dest;
> + register volatile gint32 *dest asm("g1") = _dest;
> + register gint32 tmp asm("o4");
> + register gint32 ret asm("o5");
> +
> + __asm__ __volatile__(
> + "1: ld [%%g1], %%o4\n\t"
> + " sub %%o4, 1, %%o5\n\t"
> + /* cas [%%g1], %%o4, %%o5 */
> + " .word 0xdbe0500c\n\t"
> + " cmp %%o4, %%o5\n\t"
> + " bne 1b\n\t"
> + " sub %%o5, 1, %%o5"
> + : "=&r" (tmp), "=&r" (ret)
> + : "r" (dest)
> + : "memory");
>
> - END_SPIN(_wapi_sparc_lock)
> -
> - return(ret);
> + return ret;
> }
>
> G_GNUC_UNUSED
> -static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
> +static inline gint32 InterlockedExchange(volatile gint32 *_dest, gint32 exch)
> {
> - int tmp;
> - gint32 ret;
> + register volatile gint32 *dest asm("g1") = _dest;
> + register gint32 tmp asm("o4");
> + register gint32 ret asm("o5");
> +
> + __asm__ __volatile__(
> + "1: ld [%%g1], %%o4\n\t"
> + " mov %3, %%o5\n\t"
> + /* cas [%%g1], %%o4, %%o5 */
> + " .word 0xdbe0500c\n\t"
> + " cmp %%o4, %%o5\n\t"
> + " bne 1b\n\t"
> + " nop"
> + : "=&r" (tmp), "=&r" (ret)
> + : "r" (dest), "r" (exch)
> + : "memory");
>
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - ret = *dest;
> - *dest = exch;
> -
> - END_SPIN(_wapi_sparc_lock)
> -
> - return(ret);
> + return ret;
> }
>
> G_GNUC_UNUSED
> -static inline gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
> +static inline gpointer InterlockedExchangePointer(volatile gpointer *_dest, gpointer exch)
> {
> - int tmp;
> - gpointer ret;
> -
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - ret = *dest;
> - *dest = exch;
> -
> - END_SPIN(_wapi_sparc_lock)
> + register volatile gpointer *dest asm("g1") = _dest;
> + register gpointer tmp asm("o4");
> + register gpointer ret asm("o5");
> +
> + __asm__ __volatile__(
> +#ifdef SPARCV9
> + "1: ldx [%%g1], %%o4\n\t"
> +#else
> + "1: ld [%%g1], %%o4\n\t"
> +#endif
> + " mov %3, %%o5\n\t"
> +#ifdef SPARCV9
> + /* casx [%%g1], %%o4, %%o5 */
> + " .word 0xdbf0500c\n\t"
> +#else
> + /* cas [%%g1], %%o4, %%o5 */
> + " .word 0xdbe0500c\n\t"
> +#endif
> + " cmp %%o4, %%o5\n\t"
> + " bne 1b\n\t"
> + " nop"
> + : "=&r" (tmp), "=&r" (ret)
> + : "r" (dest), "r" (exch)
> + : "memory");
>
> - return(ret);
> + return ret;
> }
>
> G_GNUC_UNUSED
> -static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
> +static inline gint32 InterlockedExchangeAdd(volatile gint32 *_dest, gint32 add)
> {
> - int tmp;
> - gint32 ret;
> -
> - BEGIN_SPIN(tmp,_wapi_sparc_lock)
> -
> - ret = *dest;
> - *dest += add;
> -
> - END_SPIN(_wapi_sparc_lock)
> + register volatile gint32 *dest asm("g1") = _dest;
> + register gint32 tmp asm("o4");
> + register gint32 ret asm("o5");
> +
> + __asm__ __volatile__(
> + "1: ld [%%g1], %%o4\n\t"
> + " add %%o4, %3, %%o5\n\t"
> + /* cas [%%g1], %%o4, %%o5 */
> + " .word 0xdbe0500c\n\t"
> + " cmp %%o4, %%o5\n\t"
> + " bne 1b\n\t"
> + " add %%o5, %3, %%o5"
> + : "=&r" (tmp), "=&r" (ret)
> + : "r" (dest), "r" (add)
> + : "memory");
>
> - return(ret);
> + return ret;
> }
>
> #elif __s390__
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>
More information about the Mono-devel-list
mailing list