Add gcc intrinsics implementations for atomic and mutex
diff --git a/configure.ac b/configure.ac
index 44b0df4..edb8820 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,8 +52,8 @@
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
diff --git a/src/hb-atomic-private.hh b/src/hb-atomic-private.hh
index 29e4146..3394afc 100644
--- a/src/hb-atomic-private.hh
+++ b/src/hb-atomic-private.hh
@@ -72,13 +72,20 @@
#endif
-#else
+#elif !defined(HB_NO_MT)
-#define HB_ATOMIC_INT_NIL 1
+#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 */
+
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 */
diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
index 9e061b9..9278643 100644
--- a/src/hb-mutex-private.hh
+++ b/src/hb-mutex-private.hh
@@ -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 @@
#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 @@
#define hb_mutex_impl_finish(M) g_static_mutex_free (M)
-#else
+#elif !defined(HB_NO_MT) && defined(__GNUC__)
-#define HB_MUTEX_IMPL_NIL 1
+#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
+
+/* 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 @@
#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); }
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index cad4426..e86a38d 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -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 @@
#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;
diff --git a/src/hb-warning.cc b/src/hb-warning.cc
index c13731b..4f1f65f 100644
--- a/src/hb-warning.cc
+++ b/src/hb-warning.cc
@@ -28,23 +28,23 @@
#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