add casArray# primop, similar to casMutVar# but for array elements
authorRyan Newton <rrnewton@gmail.com>
Thu, 29 Mar 2012 04:32:03 +0000 (00:32 -0400)
committerRyan Newton <rrnewton@gmail.com>
Wed, 21 Aug 2013 04:02:29 +0000 (00:02 -0400)
compiler/prelude/primops.txt.pp
includes/stg/MiscClosures.h
rts/Linker.c
rts/PrimOps.cmm

index e275b23..6e25d65 100644 (file)
@@ -794,6 +794,14 @@ primop  ThawArrayOp "thawArray#" GenPrimOp
   has_side_effects = True
   code_size = { primOpCodeSizeForeignCall + 4 }
 
+primop CasArrayOp  "casArray#" GenPrimOp
+   MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+   {Unsafe, machine-level atomic compare and swap on an element within an Array.}
+   with
+   out_of_line = True
+   has_side_effects = True
+
+
 ------------------------------------------------------------------------
 section "Byte Arrays"
        {Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
index b0ed03b..de5d322 100644 (file)
@@ -364,6 +364,7 @@ RTS_FUN_DECL(stg_word64ToIntegerzh);
 #endif
 
 RTS_FUN_DECL(stg_unsafeThawArrayzh);
+RTS_FUN_DECL(stg_casArrayzh);
 RTS_FUN_DECL(stg_newByteArrayzh);
 RTS_FUN_DECL(stg_newPinnedByteArrayzh);
 RTS_FUN_DECL(stg_newAlignedPinnedByteArrayzh);
index 0c7dfd2..1cb9b1f 100644 (file)
@@ -1144,6 +1144,7 @@ typedef struct _RtsSymbolVal {
       SymI_HasProto(stg_labelThreadzh)                                  \
       SymI_HasProto(stg_newArrayzh)                                     \
       SymI_HasProto(stg_newArrayArrayzh)                                \
+      SymI_HasProto(stg_casArrayzh)                                     \
       SymI_HasProto(stg_newBCOzh)                                       \
       SymI_HasProto(stg_newByteArrayzh)                                 \
       SymI_HasProto_redirect(newCAF, newDynCAF)                         \
index ced15ee..3bf5f37 100644 (file)
@@ -206,6 +206,33 @@ stg_unsafeThawArrayzh ( gcptr arr )
   }
 }
 
+stg_casArrayzh
+/* MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #) */
+{
+    W_ arr, p, ind, old, new, h, len;
+    arr = R1; // anything else?
+    ind = R2;
+    old = R3;
+    new = R4;
+
+    p = arr + SIZEOF_StgMutArrPtrs + WDS(ind);
+    (h) = foreign "C" cas(p, old, new) [];
+    
+    if (h != old) {
+        // Failure, return what was there instead of 'old':
+        RET_NP(1,h);
+    } else {
+        // Compare and Swap Succeeded:
+        if (GET_INFO(arr) == stg_MUT_ARR_PTRS_CLEAN_info) {
+           SET_HDR(arr, stg_MUT_ARR_PTRS_DIRTY_info, CCCS);
+           len = StgMutArrPtrs_ptrs(arr);
+           // The write barrier.  We must write a byte into the mark table:
+           I8[arr + SIZEOF_StgMutArrPtrs + WDS(len) + (ind >> MUT_ARR_PTRS_CARD_BITS )] = 1;
+        }
+        RET_NP(0,h);
+    }
+}
+
 stg_newArrayArrayzh ( W_ n /* words */ )
 {
     W_ words, size;