Commit 6cd3d0dc authored by Simon Marlow's avatar Simon Marlow
Browse files

atomicModifyIORef: use a local cas() instead of the global lock

This should improve scaling when using atomicModifyIORef
parent 739d8a5b
...@@ -193,7 +193,7 @@ newMutVarzh_fast ...@@ -193,7 +193,7 @@ newMutVarzh_fast
atomicModifyMutVarzh_fast atomicModifyMutVarzh_fast
{ {
W_ mv, z, x, y, r; W_ mv, f, z, x, y, r, h;
/* Args: R1 :: MutVar#, R2 :: a -> (a,b) */ /* Args: R1 :: MutVar#, R2 :: a -> (a,b) */
/* If x is the current contents of the MutVar#, then /* If x is the current contents of the MutVar#, then
...@@ -232,19 +232,15 @@ atomicModifyMutVarzh_fast ...@@ -232,19 +232,15 @@ atomicModifyMutVarzh_fast
HP_CHK_GEN_TICKY(SIZE, R1_PTR & R2_PTR, atomicModifyMutVarzh_fast); HP_CHK_GEN_TICKY(SIZE, R1_PTR & R2_PTR, atomicModifyMutVarzh_fast);
#if defined(THREADED_RTS) mv = R1;
ACQUIRE_LOCK(atomic_modify_mutvar_mutex "ptr") [R1,R2]; f = R2;
#endif
x = StgMutVar_var(R1);
TICK_ALLOC_THUNK_2(); TICK_ALLOC_THUNK_2();
CCCS_ALLOC(THUNK_2_SIZE); CCCS_ALLOC(THUNK_2_SIZE);
z = Hp - THUNK_2_SIZE + WDS(1); z = Hp - THUNK_2_SIZE + WDS(1);
SET_HDR(z, stg_ap_2_upd_info, W_[CCCS]); SET_HDR(z, stg_ap_2_upd_info, W_[CCCS]);
LDV_RECORD_CREATE(z); LDV_RECORD_CREATE(z);
StgThunk_payload(z,0) = R2; StgThunk_payload(z,0) = f;
StgThunk_payload(z,1) = x;
TICK_ALLOC_THUNK_1(); TICK_ALLOC_THUNK_1();
CCCS_ALLOC(THUNK_1_SIZE); CCCS_ALLOC(THUNK_1_SIZE);
...@@ -253,9 +249,6 @@ atomicModifyMutVarzh_fast ...@@ -253,9 +249,6 @@ atomicModifyMutVarzh_fast
LDV_RECORD_CREATE(y); LDV_RECORD_CREATE(y);
StgThunk_payload(y,0) = z; StgThunk_payload(y,0) = z;
StgMutVar_var(R1) = y;
foreign "C" dirty_MUT_VAR(BaseReg "ptr", R1 "ptr") [R1];
TICK_ALLOC_THUNK_1(); TICK_ALLOC_THUNK_1();
CCCS_ALLOC(THUNK_1_SIZE); CCCS_ALLOC(THUNK_1_SIZE);
r = y - THUNK_1_SIZE; r = y - THUNK_1_SIZE;
...@@ -263,10 +256,20 @@ atomicModifyMutVarzh_fast ...@@ -263,10 +256,20 @@ atomicModifyMutVarzh_fast
LDV_RECORD_CREATE(r); LDV_RECORD_CREATE(r);
StgThunk_payload(r,0) = z; StgThunk_payload(r,0) = z;
#if defined(THREADED_RTS) retry:
RELEASE_LOCK(atomic_modify_mutvar_mutex "ptr") []; x = StgMutVar_var(mv);
StgThunk_payload(z,1) = x;
#ifdef THREADED_RTS
(h) = foreign "C" cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y) [];
if (h != x) { goto retry; }
#else
StgMutVar_var(mv) = y;
#endif #endif
if (GET_INFO(mv) == stg_MUT_VAR_CLEAN_info) {
foreign "C" dirty_MUT_VAR(BaseReg "ptr", mv "ptr") [];
}
RET_P(r); RET_P(r);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment