Add an implementation for the CRIS and CRISv32 architectures, by Peter
authorMatthias Clasen <matthiasc@src.gnome.org>
Mon, 8 Dec 2008 04:27:37 +0000 (04:27 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Mon, 8 Dec 2008 04:27:37 +0000 (04:27 +0000)
        * configure.in:
        * glib/gatomic.c: Add an implementation for the CRIS and CRISv32
        architectures, by Peter Kjellerstedt

svn path=/trunk/; revision=7732

ChangeLog
configure.in
glib/gatomic.c

index d3d600e..013df5b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-12-07  Matthias Clasen  <mclasen@redhat.com>
+
+       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  <mclasen@redhat.com>
 
        * glib/gkeyfile.c: Some more documentation additions.
index 7fab97f..f918ea0 100644 (file)
@@ -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
index b75a8c5..3182fd7 100644 (file)
@@ -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