Use gcc intrinsic functions for atomic incr and decr

Review URL: http://codereview.appspot.com/4894055/



git-svn-id: http://skia.googlecode.com/svn/trunk@2138 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/ports/SkThread_pthread.cpp b/src/ports/SkThread_pthread.cpp
index 26f18a1..885a325 100644
--- a/src/ports/SkThread_pthread.cpp
+++ b/src/ports/SkThread_pthread.cpp
@@ -10,6 +10,35 @@
 #include <pthread.h>
 #include <errno.h>
 
+/**
+ We prefer the GCC intrinsic implementation of the atomic operations over the
+ SkMutex-based implementation. The SkMutex version suffers from static 
+ destructor ordering problems.
+ Note clang also defines the GCC version macros and implements the intrinsics.
+ TODO: Verify that gcc-style __sync_* intrinsics work on ARM
+ According to this the intrinsics are supported on ARM in LLVM 2.7+
+ http://llvm.org/releases/2.7/docs/ReleaseNotes.html
+*/
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4
+    #if (defined(__x86_64) || defined(__i386__))
+        #define GCC_INTRINSIC
+    #endif
+#endif
+
+#if defined(GCC_INTRINSIC)
+
+int32_t sk_atomic_inc(int32_t* addr)
+{
+    return __sync_fetch_and_add(addr, 1);
+}
+
+int32_t sk_atomic_dec(int32_t* addr)
+{
+    return __sync_fetch_and_add(addr, -1);
+}
+
+#else
+
 SkMutex gAtomicMutex;
 
 int32_t sk_atomic_inc(int32_t* addr)
@@ -30,6 +59,8 @@
     return value;
 }
 
+#endif
+
 //////////////////////////////////////////////////////////////////////////////
 
 static void print_pthread_error(int status)