Work around lack of __sync_fetch_and_nand in clang
authorJohan Tibell <johan.tibell@gmail.com>
Thu, 26 Jun 2014 06:39:53 +0000 (08:39 +0200)
committerJohan Tibell <johan.tibell@gmail.com>
Thu, 26 Jun 2014 06:39:53 +0000 (08:39 +0200)
clang chose to not implement this function. See
http://llvm.org/bugs/show_bug.cgi?id=8842

libraries/ghc-prim/cbits/atomic.c

index a2e64af..e3d6cc1 100644 (file)
@@ -101,32 +101,58 @@ hs_atomic_and64(volatile StgWord64 *x, StgWord64 val)
 
 // FetchNandByteArrayOp_Int
 
+// Workaround for http://llvm.org/bugs/show_bug.cgi?id=8842
+#define CAS_NAND(x, val)                                            \
+  {                                                                 \
+    __typeof__ (*(x)) tmp = *(x);                                   \
+    while (!__sync_bool_compare_and_swap(x, tmp, ~(tmp & (val)))) { \
+      tmp = *(x);                                                   \
+    }                                                               \
+    return tmp;                                                     \
+  }
+
 extern StgWord hs_atomic_nand8(volatile StgWord8 *x, StgWord val);
 StgWord
 hs_atomic_nand8(volatile StgWord8 *x, StgWord val)
 {
+#ifdef __clang__
+  CAS_NAND(x, (StgWord8) val)
+#else
   return __sync_fetch_and_nand(x, (StgWord8) val);
+#endif
 }
 
 extern StgWord hs_atomic_nand16(volatile StgWord16 *x, StgWord val);
 StgWord
 hs_atomic_nand16(volatile StgWord16 *x, StgWord val)
 {
+#ifdef __clang__
+  CAS_NAND(x, (StgWord16) val);
+#else
   return __sync_fetch_and_nand(x, (StgWord16) val);
+#endif
 }
 
 extern StgWord hs_atomic_nand32(volatile StgWord32 *x, StgWord val);
 StgWord
 hs_atomic_nand32(volatile StgWord32 *x, StgWord val)
 {
+#ifdef __clang__
+  CAS_NAND(x, (StgWord32) val);
+#else
   return __sync_fetch_and_nand(x, (StgWord32) val);
+#endif
 }
 
 extern StgWord64 hs_atomic_nand64(volatile StgWord64 *x, StgWord64 val);
 StgWord64
 hs_atomic_nand64(volatile StgWord64 *x, StgWord64 val)
 {
+#ifdef __clang__
+  CAS_NAND(x, val);
+#else
   return __sync_fetch_and_nand(x, val);
+#endif
 }
 
 // FetchOrByteArrayOp_Int