From: Matthias Clasen Date: Mon, 8 Dec 2008 04:27:37 +0000 (+0000) Subject: Add an implementation for the CRIS and CRISv32 architectures, by Peter X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=154fe24134aeb9f3a1d52890c64d227356bcbb43;p=dana%2Fcg-glib.git Add an implementation for the CRIS and CRISv32 architectures, by Peter * configure.in: * glib/gatomic.c: Add an implementation for the CRIS and CRISv32 architectures, by Peter Kjellerstedt svn path=/trunk/; revision=7732 --- diff --git a/ChangeLog b/ChangeLog index d3d600ec..013df5b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-12-07 Matthias Clasen + + Bug 508021 – Add support for the CRIS and CRISv32 architectures + + * configure.in: + * glib/gatomic.c: Add an implementation for the CRIS and CRISv32 + architectures, by Peter Kjellerstedt + 2008-12-02 Matthias Clasen * glib/gkeyfile.c: Some more documentation additions. diff --git a/configure.in b/configure.in index 7fab97f6..f918ea05 100644 --- a/configure.in +++ b/configure.in @@ -2404,6 +2404,18 @@ if test x"$GCC" = xyes; then [arm atomic implementation]) glib_memory_barrier_needed=no ;; + crisv32*|etraxfs*) + AC_MSG_RESULT([crisv32]) + AC_DEFINE_UNQUOTED(G_ATOMIC_CRISV32, 1, + [crisv32 atomic implementation]) + glib_memory_barrier_needed=no + ;; + cris*|etrax*) + AC_MSG_RESULT([cris]) + AC_DEFINE_UNQUOTED(G_ATOMIC_CRIS, 1, + [cris atomic implementation]) + glib_memory_barrier_needed=no + ;; *) AC_MSG_RESULT([none]) glib_memory_barrier_needed=yes diff --git a/glib/gatomic.c b/glib/gatomic.c index b75a8c5e..3182fd7c 100644 --- a/glib/gatomic.c +++ b/glib/gatomic.c @@ -651,9 +651,131 @@ g_atomic_pointer_compare_and_exchange (volatile gpointer *atomic, return result; } -# else /* !G_ATOMIC_ARM */ +# elif defined (G_ATOMIC_CRIS) || defined (G_ATOMIC_CRISV32) +# ifdef G_ATOMIC_CRIS +# define CRIS_ATOMIC_INT_CMP_XCHG(atomic, oldval, newval) \ + ({ \ + gboolean __result; \ + __asm__ __volatile__ ("\n" \ + "0:\tclearf\n\t" \ + "cmp.d [%[Atomic]], %[OldVal]\n\t" \ + "bne 1f\n\t" \ + "ax\n\t" \ + "move.d %[NewVal], [%[Atomic]]\n\t" \ + "bwf 0b\n" \ + "1:\tseq %[Result]" \ + : [Result] "=&r" (__result), \ + "=m" (*(atomic)) \ + : [Atomic] "r" (atomic), \ + [OldVal] "r" (oldval), \ + [NewVal] "r" (newval), \ + "g" (*(gpointer*) (atomic)) \ + : "memory"); \ + __result; \ + }) +# else +# define CRIS_ATOMIC_INT_CMP_XCHG(atomic, oldval, newval) \ + ({ \ + gboolean __result; \ + __asm__ __volatile__ ("\n" \ + "0:\tclearf p\n\t" \ + "cmp.d [%[Atomic]], %[OldVal]\n\t" \ + "bne 1f\n\t" \ + "ax\n\t" \ + "move.d %[NewVal], [%[Atomic]]\n\t" \ + "bcs 0b\n" \ + "1:\tseq %[Result]" \ + : [Result] "=&r" (__result), \ + "=m" (*(atomic)) \ + : [Atomic] "r" (atomic), \ + [OldVal] "r" (oldval), \ + [NewVal] "r" (newval), \ + "g" (*(gpointer*) (atomic)) \ + : "memory"); \ + __result; \ + }) +# endif + +#define CRIS_CACHELINE_SIZE 32 +#define CRIS_ATOMIC_BREAKS_CACHELINE(atomic) \ + (((gulong)(atomic) & (CRIS_CACHELINE_SIZE - 1)) > (CRIS_CACHELINE_SIZE - sizeof (atomic))) + +gint __g_atomic_int_exchange_and_add (volatile gint *atomic, + gint val); +void __g_atomic_int_add (volatile gint *atomic, + gint val); +gboolean __g_atomic_int_compare_and_exchange (volatile gint *atomic, + gint oldval, + gint newval); +gboolean __g_atomic_pointer_compare_and_exchange (volatile gpointer *atomic, + gpointer oldval, + gpointer newval); + +gboolean +g_atomic_pointer_compare_and_exchange (volatile gpointer *atomic, + gpointer oldval, + gpointer newval) +{ + if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic))) + return __g_atomic_pointer_compare_and_exchange (atomic, oldval, newval); + + return CRIS_ATOMIC_INT_CMP_XCHG (atomic, oldval, newval); +} + +gboolean +g_atomic_int_compare_and_exchange (volatile gint *atomic, + gint oldval, + gint newval) +{ + if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic))) + return __g_atomic_int_compare_and_exchange (atomic, oldval, newval); + + return CRIS_ATOMIC_INT_CMP_XCHG (atomic, oldval, newval); +} + +gint +g_atomic_int_exchange_and_add (volatile gint *atomic, + gint val) +{ + gint result; + + if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic))) + return __g_atomic_int_exchange_and_add (atomic, val); + + do + result = *atomic; + while (!CRIS_ATOMIC_INT_CMP_XCHG (atomic, result, result + val)); + + return result; +} + +void +g_atomic_int_add (volatile gint *atomic, + gint val) +{ + gint result; + + if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic))) + return __g_atomic_int_add (atomic, val); + + do + result = *atomic; + while (!CRIS_ATOMIC_INT_CMP_XCHG (atomic, result, result + val)); +} + +/* We need the atomic mutex for atomic operations where the atomic variable + * breaks the 32 byte cache line since the CRIS architecture does not support + * atomic operations on such variables. Fortunately this should be rare. + */ +# define DEFINE_WITH_MUTEXES +# define g_atomic_int_exchange_and_add __g_atomic_int_exchange_and_add +# define g_atomic_int_add __g_atomic_int_add +# define g_atomic_int_compare_and_exchange __g_atomic_int_compare_and_exchange +# define g_atomic_pointer_compare_and_exchange __g_atomic_pointer_compare_and_exchange + +# else /* !G_ATOMIC_* */ # define DEFINE_WITH_MUTEXES -# endif /* G_ATOMIC_IA64 */ +# endif /* G_ATOMIC_* */ #else /* !__GNUC__ */ # ifdef G_PLATFORM_WIN32 # define DEFINE_WITH_WIN32_INTERLOCKED