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===-----------------------------------------------------------------------===