[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