[oe-commits] Pratheesh Gangadhar : glib-2.0 2.21.4: add armv6 atomic ops, this fixes 100% utilization hangs when doing DSP based GStreamer playback

git version control git at git.openembedded.org
Thu Aug 27 14:05:21 UTC 2009


Module: openembedded.git
Branch: org.openembedded.dev
Commit: 1eb89aacbc6830fe242eac36ba8bcb61d98807f5
URL:    http://gitweb.openembedded.net/?p=openembedded.git&a=commit;h=1eb89aacbc6830fe242eac36ba8bcb61d98807f5

Author: Pratheesh Gangadhar <pratheesh.gangadhar at gmail.com>
Date:   Thu Aug 27 02:51:00 2009 +0530

glib-2.0 2.21.4: add armv6 atomic ops, this fixes 100% utilization hangs when doing DSP based GStreamer playback

GLIB by default uses ARMV5 instructions for emulating atomic operations and this patch (derived from https://stage.maemo.org/svn/maemo/projects/haf/trunk/glib/debian/patches/25-gatomic.patch) make use ARMV6 atomic instructions instead. CPU goes into "sched_yield" while loop during hang - due to a race condition triggered by  high rate context switching while running DSP plugins.

---

 recipes/glib-2.0/files/gatomic_armv6.patch |  260 ++++++++++++++++++++++++++++
 recipes/glib-2.0/glib-2.0_2.21.4.bb        |    6 +-
 2 files changed, 265 insertions(+), 1 deletions(-)

diff --git a/recipes/glib-2.0/files/gatomic_armv6.patch b/recipes/glib-2.0/files/gatomic_armv6.patch
new file mode 100755
index 0000000..04bae15
--- /dev/null
+++ b/recipes/glib-2.0/files/gatomic_armv6.patch
@@ -0,0 +1,260 @@
+--- glib-2.18.1.orig/configure.in
++++ glib-2.18.1/configure.in
+@@ -2396,9 +2396,15 @@ if test x"$GCC" = xyes; then
+       ;;	
+     arm*)
+       AC_MSG_RESULT([arm])
+-      AC_DEFINE_UNQUOTED(G_ATOMIC_ARM, 1,
+-                         [arm atomic implementation])
+-      glib_memory_barrier_needed=no
++      AC_MSG_CHECKING(arm atomic operations type)
++      AC_MSG_RESULT(inline asm)
++      AC_DEFINE_UNQUOTED(G_ATOMIC_ARM, 6,
++                         [armv6 atomic implementation])
++      glib_memory_barrier_needed=yes
++      dnl AC_MSG_RESULT(kernel helper)
++      dnl AC_DEFINE_UNQUOTED(G_ATOMIC_ARM_LINUX, 1,
++      dnl                   [special arm linux implementation])
++      dnl glib_memory_barrier_needed=yes
+       ;;
+     *)
+       AC_MSG_RESULT([none])
+--- /tmp/gatomic.c	2009-08-27 02:08:32.000000000 +0530
++++ glib-2.21.4/glib/gatomic.c	2009-08-27 02:08:49.000000000 +0530
+@@ -561,6 +561,7 @@ g_atomic_pointer_compare_and_exchange (v
+ #    error "Your system has an unsupported pointer size"
+ #  endif /* GLIB_SIZEOF_VOID_P */
+ # elif defined (G_ATOMIC_ARM)
++#  if (G_ATOMIC_ARM < 6)
+ static volatile int atomic_spin = 0;
+ 
+ static int atomic_spin_trylock (void)
+@@ -651,6 +652,218 @@ g_atomic_pointer_compare_and_exchange (v
+ 
+   return result;
+ }
++ #  else /* G_ATOMIC_ARM < 6 */
++ gint
++ g_atomic_int_exchange_and_add (volatile gint *atomic,
++ 			       gint           val)
++ {
++   unsigned long result;
++   int old, tmp;
++ 
++   do {
++     asm volatile (
++       "ldrex %0, [%3]\n"
++       "add %1, %0, %4\n"
++       "strex %2, %1, [%3]\n"
++       : "=&r" (old), "=&r" (tmp), "=&r" (result)
++       : "r" (atomic), "Ir" (val)
++       : "cc", "memory");
++   } while (result);
++   return old;
++ }
++ 
++ void
++ g_atomic_int_add (volatile gint *atomic,
++ 		  gint           val)
++ {
++   unsigned long result;
++   int tmp;
++ 
++   do {
++     asm volatile (
++       "ldrex %0, [%2]\n"
++       "add %0, %0, %3\n"
++       "strex %1, %0, [%2]\n"
++       : "=&r" (tmp), "=&r" (result)
++       : "r" (atomic), "Ir" (val)
++       : "cc", "memory");
++   } while (result);
++ }
++ 
++ gboolean
++ g_atomic_int_compare_and_exchange (volatile gint *atomic,
++ 				   gint           oldval,
++ 				   gint           newval)
++ {
++   unsigned long result;
++   int old;
++ 
++   asm volatile (
++     "ldrex %1, [%2]\n"
++     "mov %0, #1\n"
++     "teq %1, %3\n"
++     "strexeq %0, %4, [%2]\n"
++     : "=&r" (result), "=&r" (old)
++     : "r" (atomic), "Ir" (oldval), "r" (newval)
++     : "cc", "memory");
++   return (result) ? FALSE : TRUE;
++ }
++ 
++ gboolean
++ g_atomic_pointer_compare_and_exchange (volatile gpointer *atomic,
++ 				       gpointer           oldval,
++ 				       gpointer           newval)
++ {
++   unsigned long result;
++   void *old;
++ 
++   asm volatile (
++     "ldrex %1, [%2]\n"
++     "mov %0, #1\n"
++     "teq %1, %3\n"
++     "strexeq %0, %4, [%2]\n"
++     : "=&r" (result), "=&r" (old)
++     : "r" (atomic), "Ir" (oldval), "r" (newval)
++     : "cc", "memory");
++   return (result) ? FALSE : TRUE;
++ }
++ 
++ gint
++ (g_atomic_int_get) (volatile gint *atomic)
++ {
++   return *atomic;
++ }
++ 
++ void
++ (g_atomic_int_set) (volatile gint *atomic,
++                   gint           newval)
++ {
++   unsigned long result;
++ 
++   do {
++     asm volatile (
++       "ldrex %0, [%1]\n"
++       "strex %0, %2, [%1]\n"
++       : "=&r" (result)
++       : "r" (atomic), "r" (newval)
++       : "cc", "memory");
++   } while (result);
++ }
++ 
++ gpointer
++ (g_atomic_pointer_get) (volatile gpointer *atomic)
++ {
++   return *atomic;
++ }
++ 
++ void
++ (g_atomic_pointer_set) (volatile gpointer *atomic,
++                       gpointer           newval)
++ {
++   unsigned long result;
++ 
++   do {
++     asm volatile (
++       "ldrex %0, [%1]\n"
++       "strex %0, %2, [%1]\n"
++       : "=&r" (result)
++       : "r" (atomic), "r" (newval)
++       : "cc", "memory");
++   } while (result);
++ }
++#  endif /* G_ATOMIC_ARM < 6 */
++ # elif defined(G_ATOMIC_ARM_LINUX)
++ /* use special helper functions provided by the linux kernel */
++ 
++ typedef void (_khelper_barrier_t)(void);
++ #define _khelper_barrier (*(_khelper_barrier_t *)0xffff0fa0)
++ #define G_ATOMIC_MEMORY_BARRIER _khelper_barrier()
++ /* scratchbox/qemu explodes on barrier */
++ /*#define G_ATOMIC_MEMORY_BARRIER while(0)*/
++ typedef int (_khelper_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
++ #define _khelper_cmpxchg (*(_khelper_cmpxchg_t *)0xffff0fc0)
++ 
++ gint
++ g_atomic_int_exchange_and_add (volatile gint *atomic,
++ 			       gint           val)
++ {
++   int result;
++   int old, new;
++ 
++   do {
++     old = *atomic;
++     new = old + val;
++     result = _khelper_cmpxchg(old, new, atomic);
++   } while (result);
++   return old;
++ }
++ 
++ void
++ g_atomic_int_add (volatile gint *atomic,
++ 		  gint           val)
++ {
++   int result;
++   int old, new;
++ 
++   do {
++     old = *atomic;
++     new = old + val;
++     result = _khelper_cmpxchg(old, new, atomic);
++   } while (result);
++ }
++ 
++ gboolean
++ g_atomic_int_compare_and_exchange (volatile gint *atomic,
++ 				   gint           oldval,
++ 				   gint           newval)
++ {
++   int result;
++ 
++   result = _khelper_cmpxchg(oldval, newval, atomic);
++   return (result) ? FALSE : TRUE;
++ }
++ 
++ gboolean
++ g_atomic_pointer_compare_and_exchange (volatile gpointer *atomic,
++ 				       gpointer           oldval,
++ 				       gpointer           newval)
++ {
++   int result;
++ 
++   result = _khelper_cmpxchg(*((int *) &oldval),
++                             *((int *) &newval),
++                             (int *) atomic);
++   return (result) ? FALSE : TRUE;
++ }
++ 
++ gint
++ (g_atomic_int_get) (volatile gint *atomic)
++ {
++   return *atomic;
++ }
++ 
++ void
++ (g_atomic_int_set) (volatile gint *atomic,
++                   gint           newval)
++ {
++   while (_khelper_cmpxchg(*atomic, newval, atomic));
++ }
++ 
++ gpointer
++ (g_atomic_pointer_get) (volatile gpointer *atomic)
++ {
++   return *atomic;
++ }
++ 
++ void
++ (g_atomic_pointer_set) (volatile gpointer *atomic,
++                       gpointer           newval)
++ {
++   while (_khelper_cmpxchg(*((int *) atomic),
++                           *((int *) &newval),
++                           (int *) atomic));
++ }
++
+ # elif defined (G_ATOMIC_CRIS) || defined (G_ATOMIC_CRISV32)
+ #  ifdef G_ATOMIC_CRIS
+ #   define CRIS_ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)		\
+@@ -954,7 +1167,8 @@ void
+   g_mutex_unlock (g_atomic_mutex);
+ }
+ #endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */   
+-#elif defined (G_ATOMIC_OP_MEMORY_BARRIER_NEEDED)
++#elif (defined (G_ATOMIC_OP_MEMORY_BARRIER_NEEDED) && \
++       !defined(G_ATOMIC_ARM) && !defined(G_ATOMIC_ARM_LINUX))
+ gint
+ (g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
+ {
diff --git a/recipes/glib-2.0/glib-2.0_2.21.4.bb b/recipes/glib-2.0/glib-2.0_2.21.4.bb
index 4be0949..ca9e4b2 100644
--- a/recipes/glib-2.0/glib-2.0_2.21.4.bb
+++ b/recipes/glib-2.0/glib-2.0_2.21.4.bb
@@ -3,9 +3,13 @@ require glib.inc
 DEFAULT_PREFERENCE = "-1"
 DEFAULT_PREFERENCE_angstrom = "1"
 
+PR = "r1"
+
 SRC_URI = "\
   http://ftp.gnome.org/pub/GNOME/sources/glib/2.21/glib-${PV}.tar.bz2 \
   file://glibconfig-sysdefs.h \
   file://configure-libtool.patch;patch=1 \
 "
-SRC_URI_append_arm = " file://atomic-thumb.patch;patch=1"
+SRC_URI_append_arm = " file://atomic-thumb.patch;patch=1 \
+			file://gatomic_armv6.patch;patch=1 \
+"





More information about the Openembedded-commits mailing list