[Mono-dev] _wapi_sparc_lock
David S. Miller
davem at davemloft.net
Fri Mar 24 22:08:56 EST 2006
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__
More information about the Mono-devel-list
mailing list