summaryrefslogtreecommitdiff
path: root/libraries/ghc-prim/cbits/atomic.c
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2018-02-03 11:37:01 -0500
committerBen Gamari <ben@smart-cactus.org>2018-02-03 11:37:14 -0500
commit217e4170bdce3df28a667803ce5e619553bfecdd (patch)
tree1e548bae29aecc72ce257dc962025c1388a7a7b5 /libraries/ghc-prim/cbits/atomic.c
parentfdf518c708dc5a34ae810c5d5f3a4db812d226f0 (diff)
downloadhaskell-217e4170bdce3df28a667803ce5e619553bfecdd.tar.gz
ghc-prim: Emulate C11 atomics when not available
GCC's __sync primitives apparently "usually" imply a full barrier, meaning they can be used to emulate the more precise C11 atomics albeit with a loss of efficiency. This restores compatibility with GCC 4.4. This partially reverts commit 59de290928e6903337f31c1f8107ac8a98ea145d. Test Plan: Validate on Centos Reviewers: hvr, simonmar, trommler Subscribers: rwbarton, thomie, erikd, carter GHC Trac Issues: #14244 Differential Revision: https://phabricator.haskell.org/D4364
Diffstat (limited to 'libraries/ghc-prim/cbits/atomic.c')
-rw-r--r--libraries/ghc-prim/cbits/atomic.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/libraries/ghc-prim/cbits/atomic.c b/libraries/ghc-prim/cbits/atomic.c
index b091d22b58..2ded465fcd 100644
--- a/libraries/ghc-prim/cbits/atomic.c
+++ b/libraries/ghc-prim/cbits/atomic.c
@@ -264,33 +264,53 @@ hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
// __ATOMIC_SEQ_CST: Full barrier in both directions (hoisting and sinking
// of code) and synchronizes with acquire loads and release stores in
// all threads.
+//
+// When we lack C11 atomics support we emulate these using the old GCC __sync
+// primitives which the GCC documentation claims "usually" implies a full
+// barrier.
extern StgWord hs_atomicread8(StgWord x);
StgWord
hs_atomicread8(StgWord x)
{
+#if HAVE_C11_ATOMICS
return __atomic_load_n((StgWord8 *) x, __ATOMIC_SEQ_CST);
+#else
+ return __sync_add_and_fetch((StgWord8 *) x, 0);
+#endif
}
extern StgWord hs_atomicread16(StgWord x);
StgWord
hs_atomicread16(StgWord x)
{
+#if HAVE_C11_ATOMICS
return __atomic_load_n((StgWord16 *) x, __ATOMIC_SEQ_CST);
+#else
+ return __sync_add_and_fetch((StgWord16 *) x, 0);
+#endif
}
extern StgWord hs_atomicread32(StgWord x);
StgWord
hs_atomicread32(StgWord x)
{
+#if HAVE_C11_ATOMICS
return __atomic_load_n((StgWord32 *) x, __ATOMIC_SEQ_CST);
+#else
+ return __sync_add_and_fetch((StgWord32 *) x, 0);
+#endif
}
extern StgWord64 hs_atomicread64(StgWord x);
StgWord64
hs_atomicread64(StgWord x)
{
+#if HAVE_C11_ATOMICS
return __atomic_load_n((StgWord64 *) x, __ATOMIC_SEQ_CST);
+#else
+ return __sync_add_and_fetch((StgWord64 *) x, 0);
+#endif
}
// AtomicWriteByteArrayOp_Int
@@ -301,26 +321,42 @@ extern void hs_atomicwrite8(StgWord x, StgWord val);
void
hs_atomicwrite8(StgWord x, StgWord val)
{
+#if HAVE_C11_ATOMICS
__atomic_store_n((StgWord8 *) x, (StgWord8) val, __ATOMIC_SEQ_CST);
+#else
+ while (!__sync_bool_compare_and_swap((StgWord8 *) x, *(StgWord8 *) x, (StgWord8) val));
+#endif
}
extern void hs_atomicwrite16(StgWord x, StgWord val);
void
hs_atomicwrite16(StgWord x, StgWord val)
{
+#if HAVE_C11_ATOMICS
__atomic_store_n((StgWord16 *) x, (StgWord16) val, __ATOMIC_SEQ_CST);
+#else
+ while (!__sync_bool_compare_and_swap((StgWord16 *) x, *(StgWord16 *) x, (StgWord16) val));
+#endif
}
extern void hs_atomicwrite32(StgWord x, StgWord val);
void
hs_atomicwrite32(StgWord x, StgWord val)
{
+#if HAVE_C11_ATOMICS
__atomic_store_n((StgWord32 *) x, (StgWord32) val, __ATOMIC_SEQ_CST);
+#else
+ while (!__sync_bool_compare_and_swap((StgWord32 *) x, *(StgWord32 *) x, (StgWord32) val));
+#endif
}
extern void hs_atomicwrite64(StgWord x, StgWord64 val);
void
hs_atomicwrite64(StgWord x, StgWord64 val)
{
+#if HAVE_C11_ATOMICS
__atomic_store_n((StgWord64 *) x, (StgWord64) val, __ATOMIC_SEQ_CST);
+#else
+ while (!__sync_bool_compare_and_swap((StgWord64 *) x, *(StgWord64 *) x, (StgWord64) val));
+#endif
}