summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/cmm/CmmParse.y7
-rw-r--r--includes/Cmm.h10
-rw-r--r--rts/PrimOps.cmm10
3 files changed, 21 insertions, 6 deletions
diff --git a/compiler/cmm/CmmParse.y b/compiler/cmm/CmmParse.y
index 128cc4e4e1..b8c100a3c0 100644
--- a/compiler/cmm/CmmParse.y
+++ b/compiler/cmm/CmmParse.y
@@ -987,7 +987,12 @@ callishMachOps = listToUFM $
( "popcnt8", (,) $ MO_PopCnt W8 ),
( "popcnt16", (,) $ MO_PopCnt W16 ),
( "popcnt32", (,) $ MO_PopCnt W32 ),
- ( "popcnt64", (,) $ MO_PopCnt W64 )
+ ( "popcnt64", (,) $ MO_PopCnt W64 ),
+
+ ( "cmpxchg8", (,) $ MO_Cmpxchg W8 ),
+ ( "cmpxchg16", (,) $ MO_Cmpxchg W16 ),
+ ( "cmpxchg32", (,) $ MO_Cmpxchg W32 ),
+ ( "cmpxchg64", (,) $ MO_Cmpxchg W64 )
-- ToDo: the rest, maybe
-- edit: which rest?
diff --git a/includes/Cmm.h b/includes/Cmm.h
index 3b9a5a6794..9b7a4e4608 100644
--- a/includes/Cmm.h
+++ b/includes/Cmm.h
@@ -179,6 +179,16 @@
#endif
/* -----------------------------------------------------------------------------
+ Atomic memory operations.
+ -------------------------------------------------------------------------- */
+
+#if SIZEOF_W == 4
+#define cmpxchgW cmpxchg32
+#elif SIZEOF_W == 8
+#define cmpxchgW cmpxchg64
+#endif
+
+/* -----------------------------------------------------------------------------
Heap/stack access, and adjusting the heap/stack pointers.
-------------------------------------------------------------------------- */
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index 60d8106983..b468c33df6 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -221,7 +221,7 @@ stg_casIntArrayzh( gcptr arr, W_ ind, W_ old, W_ new )
W_ p, h;
p = arr + SIZEOF_StgArrBytes + WDS(ind);
- (h) = ccall cas(p, old, new);
+ (h) = prim %cmpxchgW(p, old, new);
return(h);
}
@@ -338,7 +338,7 @@ stg_casArrayzh ( gcptr arr, W_ ind, gcptr old, gcptr new )
W_ p, len;
p = arr + SIZEOF_StgMutArrPtrs + WDS(ind);
- (h) = ccall cas(p, old, new);
+ (h) = prim %cmpxchgW(p, old, new);
if (h != old) {
// Failure, return what was there instead of 'old':
@@ -490,7 +490,7 @@ stg_casSmallArrayzh ( gcptr arr, W_ ind, gcptr old, gcptr new )
W_ p, len;
p = arr + SIZEOF_StgSmallMutArrPtrs + WDS(ind);
- (h) = ccall cas(p, old, new);
+ (h) = prim %cmpxchgW(p, old, new);
if (h != old) {
// Failure, return what was there instead of 'old':
@@ -530,7 +530,7 @@ stg_casMutVarzh ( gcptr mv, gcptr old, gcptr new )
{
gcptr h;
- (h) = ccall cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, old, new);
+ (h) = prim %cmpxchgW(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, old, new);
if (h != old) {
return (1,h);
} else {
@@ -606,7 +606,7 @@ stg_atomicModifyMutVarzh ( gcptr mv, gcptr f )
x = StgMutVar_var(mv);
StgThunk_payload(z,1) = x;
#ifdef THREADED_RTS
- (h) = ccall cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y);
+ (h) = prim %cmpxchgW(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y);
if (h != x) { goto retry; }
#else
StgMutVar_var(mv) = y;