Add gcc intrinsics implementations for atomic and mutex
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 5 Jun 2012 20:34:49 +0000 (16:34 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 5 Jun 2012 20:40:23 +0000 (16:40 -0400)
configure.ac
src/hb-atomic-private.hh
src/hb-mutex-private.hh
src/hb-object-private.hh
src/hb-warning.cc

index 44b0df4..edb8820 100644 (file)
@@ -52,8 +52,8 @@ AC_SUBST(HB_LIBTOOL_VERSION_INFO)
 dnl GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
 
 # Functions and headers
-AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap _setmode isatty)
-AC_CHECK_HEADERS(unistd.h sys/mman.h io.h)
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize sched_yield mmap _setmode isatty)
+AC_CHECK_HEADERS(unistd.h sys/mman.h sched.h io.h)
 
 # Compiler flags
 AC_CANONICAL_HOST
index 29e4146..3394afc 100644 (file)
@@ -72,13 +72,20 @@ typedef int hb_atomic_int_t;
 #endif
 
 
-#else
+#elif !defined(HB_NO_MT)
+
+#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V)       (((AI) += (V)) - (V))
+
+
+#else /* HB_NO_MT */
 
-#define HB_ATOMIC_INT_NIL 1
 typedef int hb_atomic_int_t;
 #define hb_atomic_int_add(AI, V)       (((AI) += (V)) - (V))
 
 #endif
 
+/* TODO Add tracing. */
 
 #endif /* HB_ATOMIC_PRIVATE_HH */
index 9e061b9..9278643 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2007  Chris Wilson
  * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
+ * Copyright © 2011,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -53,7 +53,7 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
 #define hb_mutex_impl_finish(M)        DeleteCriticalSection (M)
 
 
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
 
 #include <pthread.h>
 typedef pthread_mutex_t hb_mutex_impl_t;
@@ -75,15 +75,50 @@ typedef GStaticMutex hb_mutex_impl_t;
 #define hb_mutex_impl_finish(M)        g_static_mutex_free (M)
 
 
+#elif !defined(HB_NO_MT) && defined(__GNUC__)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
 #else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
 
-#define HB_MUTEX_IMPL_NIL 1
+/* This actually is not a totally awful implementation. */
 typedef volatile int hb_mutex_impl_t;
 #define HB_MUTEX_IMPL_INIT     0
-#define hb_mutex_impl_init(M)  ((void) (*(M) = 0))
-#define hb_mutex_impl_lock(M)  ((void) (*(M) = 1))
-#define hb_mutex_impl_unlock(M)        ((void) (*(M) = 0))
-#define hb_mutex_impl_finish(M)        ((void) (*(M) = 2))
+#define hb_mutex_impl_init(M)  *(M) = 0
+#define hb_mutex_impl_lock(M)  HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
+#define hb_mutex_impl_unlock(M)        __sync_lock_release (M)
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
+
+
+#elif !defined(HB_NO_MT)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     0
+#define hb_mutex_impl_init(M)  *(M) = 0
+#define hb_mutex_impl_lock(M)  HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
+#define hb_mutex_impl_unlock(M)        (*(M))--;
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
+
+
+#else /* HB_NO_MT */
+
+typedef int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT     0
+#define hb_mutex_impl_init(M)  HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_lock(M)  HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_unlock(M)        HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_finish(M)        HB_STMT_START {} HB_STMT_END
 
 #endif
 
@@ -91,6 +126,8 @@ typedef volatile int hb_mutex_impl_t;
 #define HB_MUTEX_INIT          {HB_MUTEX_IMPL_INIT}
 struct hb_mutex_t
 {
+  /* TODO Add tracing. */
+
   hb_mutex_impl_t m;
 
   inline void init   (void) { hb_mutex_impl_init   (&m); }
index cad4426..e86a38d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright © 2007  Chris Wilson
  * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
+ * Copyright © 2011,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -68,6 +68,8 @@ struct hb_reference_count_t
 #define HB_USER_DATA_ARRAY_INIT {HB_LOCKABLE_SET_INIT}
 struct hb_user_data_array_t
 {
+  /* TODO Add tracing. */
+
   struct hb_user_data_item_t {
     hb_user_data_key_t *key;
     void *data;
index c13731b..4f1f65f 100644 (file)
 #include "hb-mutex-private.hh"
 
 
-#if !defined(HB_NO_MT) && defined(HB_ATOMIC_INT_NIL)
+#if defined(HB_ATOMIC_INT_NIL)
 #ifdef _MSC_VER
-#pragma message("Could not find any system to define atomic_int macros, library will NOT be thread-safe")
+#pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe")
 #else
-#warning "Could not find any system to define atomic_int macros, library will NOT be thread-safe"
+#warning "Could not find any system to define atomic_int macros, library may NOT be thread-safe"
 #endif
 #endif
 
-#if !defined(HB_NO_MT) && defined(HB_MUTEX_IMPL_NIL)
+#if defined(HB_MUTEX_IMPL_NIL)
 #ifdef _MSC_VER
-#pragma message("Could not find any system to define mutex macros, library will NOT be thread-safe")
+#pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe")
 #else
-#warning "Could not find any system to define mutex macros, library will NOT be thread-safe"
+#warning "Could not find any system to define mutex macros, library may NOT be thread-safe"
 #endif
 #endif
 
-#if !defined(HB_NO_MT) && (defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL))
+#if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL)
 #ifdef _MSC_VER
 #pragma message("To suppress these warnings, define HB_NO_MT")
 #else