[LLVMdev] [patch] atomic functions on darwin

David Fang fang at csl.cornell.edu
Tue Feb 28 00:17:43 PST 2012


Hi,
 	Some time in the last few weeks I noticed my cmake build of 
svn-trunk on powerpc-darwin8 start to warn about atomics being unavailable 
and thus building thread-unsafe.  I just looked into it and found an easy 
solution, using the atomic functions in <libkern/OSAtomic.h> in 
/usr/include.  The attached patch does this and also modifies the cmake 
and autoconf tests to 'pass' LLVM_HAS_ATOMICS.  I'm able to build 
LLVMSupport.dylib with this patch.
 	Please review, revise, criticize?

Fang

-- 
David Fang
http://www.csl.cornell.edu/~fang/
-------------- next part --------------
Index: cmake/modules/CheckAtomic.cmake
===================================================================
--- cmake/modules/CheckAtomic.cmake	(revision 151623)
+++ cmake/modules/CheckAtomic.cmake	(working copy)
@@ -6,6 +6,9 @@
 #ifdef _MSC_VER
 #include <windows.h>
 #endif
+#ifdef __APPLE__
+#include <libkern/OSAtomic.h>
+#endif
 int main() {
 #ifdef _MSC_VER
         volatile LONG val = 1;
@@ -13,6 +16,12 @@
         InterlockedCompareExchange(&val, 0, 1);
         InterlockedIncrement(&val);
         InterlockedDecrement(&val);
+#elif	defined(__APPLE__)
+	int32_t val = 1;
+        OSMemoryBarrier();
+        OSAtomicCompareAndSwap32(0, 1, &val);
+        OSAtomicIncrement32(&val);
+        OSAtomicDecrement32(&val);
 #else
         volatile unsigned long val = 1;
         __sync_synchronize();
Index: include/llvm/Support/Atomic.h
===================================================================
--- include/llvm/Support/Atomic.h	(revision 151623)
+++ include/llvm/Support/Atomic.h	(working copy)
@@ -22,6 +22,8 @@
 
 #ifdef _MSC_VER
     typedef long cas_flag;
+#elif defined(__APPLE__)
+    typedef int32_t cas_flag;
 #else
     typedef uint32_t cas_flag;
 #endif
Index: lib/Support/Atomic.cpp
===================================================================
--- lib/Support/Atomic.cpp	(revision 151623)
+++ lib/Support/Atomic.cpp	(working copy)
@@ -21,17 +21,27 @@
 #undef MemoryFence
 #endif
 
+#if defined(__APPLE__)
+#include <libkern/OSAtomic.h>
+// __APPLE__ should take precedence over __GNUC__
+// sys::cas_flag is int32_t from Support/Atomic.h, so use '32' variants
+// prototypes lack the 'volatile' qualifier, so we need to cast them away
+template <class T>
+static inline
+T* vcast(volatile T* ptr) { return const_cast<T*>(ptr); }
+#endif
+
 void sys::MemoryFence() {
 #if LLVM_HAS_ATOMICS == 0
   return;
-#else
-#  if defined(__GNUC__)
+#elif defined(__APPLE__)
+  OSMemoryBarrier();
+#elif defined(__GNUC__)
   __sync_synchronize();
-#  elif defined(_MSC_VER)
+#elif defined(_MSC_VER)
   MemoryBarrier();
-#  else
+#else
 # error No memory fence implementation for your platform!
-#  endif
 #endif
 }
 
@@ -43,6 +53,8 @@
   if (result == old_value)
     *ptr = new_value;
   return result;
+#elif defined(__APPLE__)
+  return OSAtomicCompareAndSwap32(old_value, new_value, vcast(ptr));
 #elif defined(__GNUC__)
   return __sync_val_compare_and_swap(ptr, old_value, new_value);
 #elif defined(_MSC_VER)
@@ -56,6 +68,8 @@
 #if LLVM_HAS_ATOMICS == 0
   ++(*ptr);
   return *ptr;
+#elif defined(__APPLE__)
+  return OSAtomicIncrement32(vcast(ptr));
 #elif defined(__GNUC__)
   return __sync_add_and_fetch(ptr, 1);
 #elif defined(_MSC_VER)
@@ -69,6 +83,8 @@
 #if LLVM_HAS_ATOMICS == 0
   --(*ptr);
   return *ptr;
+#elif defined(__APPLE__)
+  return OSAtomicDecrement32(vcast(ptr));
 #elif defined(__GNUC__)
   return __sync_sub_and_fetch(ptr, 1);
 #elif defined(_MSC_VER)
@@ -82,6 +98,8 @@
 #if LLVM_HAS_ATOMICS == 0
   *ptr += val;
   return *ptr;
+#elif defined(__APPLE__)
+  return OSAtomicAdd32(val, vcast(ptr));
 #elif defined(__GNUC__)
   return __sync_add_and_fetch(ptr, val);
 #elif defined(_MSC_VER)
Index: autoconf/configure.ac
===================================================================
--- autoconf/configure.ac	(revision 151623)
+++ autoconf/configure.ac	(working copy)
@@ -1378,19 +1378,23 @@
 AC_LINK_IFELSE(
   AC_LANG_SOURCE(
     [[int main() {
+	#if defined(__APPLE__)
+	// atomic functions assumed to be in <libkern/OSAtomic.h>
+	#else
         volatile unsigned long val = 1;
         __sync_synchronize();
         __sync_val_compare_and_swap(&val, 1, 0);
         __sync_add_and_fetch(&val, 1);
         __sync_sub_and_fetch(&val, 1);
+	#endif
         return 0;
       }
     ]]),
   AC_LANG_POP([C++])
   AC_MSG_RESULT(yes)
-  AC_DEFINE(LLVM_HAS_ATOMICS, 1, Has gcc/MSVC atomic intrinsics),
+  AC_DEFINE(LLVM_HAS_ATOMICS, 1, Has gcc/MSVC/Apple atomic intrinsics),
   AC_MSG_RESULT(no)
-  AC_DEFINE(LLVM_HAS_ATOMICS, 0, Has gcc/MSVC atomic intrinsics)
+  AC_DEFINE(LLVM_HAS_ATOMICS, 0, Has gcc/MSVC/Apple atomic intrinsics)
   AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing]))
 
 dnl===-----------------------------------------------------------------------===


More information about the llvm-dev mailing list