diff options
author | Edward Z. Yang <ezyang@mit.edu> | 2013-07-08 11:03:35 -0700 |
---|---|---|
committer | Edward Z. Yang <ezyang@mit.edu> | 2013-07-09 11:29:11 -0700 |
commit | 70e20631742e516c6a11c3c112fbd5b4a08c15ac (patch) | |
tree | d0097f8b1c8e5c0a67b26bb950c036ea7684c65d /rts/HeapStackCheck.cmm | |
parent | ca9a431401755f119d97dec59a1fc963a8e9f681 (diff) | |
download | haskell-70e20631742e516c6a11c3c112fbd5b4a08c15ac.tar.gz |
Implement atomicReadMVar, fixing #4001.
We add the invariant to the MVar blocked threads queue that
threads blocked on an atomic read are always at the front of
the queue. This invariant is easy to maintain, since takers
are only ever added to the end of the queue.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
Diffstat (limited to 'rts/HeapStackCheck.cmm')
-rw-r--r-- | rts/HeapStackCheck.cmm | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/rts/HeapStackCheck.cmm b/rts/HeapStackCheck.cmm index fbceb7691a..20cd9dffb9 100644 --- a/rts/HeapStackCheck.cmm +++ b/rts/HeapStackCheck.cmm @@ -487,11 +487,11 @@ stg_block_noregs /* ----------------------------------------------------------------------------- * takeMVar/putMVar-specific blocks * - * Stack layout for a thread blocked in takeMVar: + * Stack layout for a thread blocked in takeMVar/atomicReadMVar: * * ret. addr * ptr to MVar (R1) - * stg_block_takemvar_info + * stg_block_takemvar_info (or stg_block_readmvar_info) * * Stack layout for a thread blocked in putMVar: * @@ -531,6 +531,33 @@ stg_block_takemvar /* mvar passed in R1 */ BLOCK_BUT_FIRST(stg_block_takemvar_finally); } +INFO_TABLE_RET ( stg_block_atomicreadmvar, RET_SMALL, W_ info_ptr, P_ mvar ) + return () +{ + jump stg_atomicReadMVarzh(mvar); +} + +// code fragment executed just before we return to the scheduler +stg_block_atomicreadmvar_finally +{ + W_ r1, r3; + r1 = R1; + r3 = R3; + unlockClosure(R3, stg_MVAR_DIRTY_info); + R1 = r1; + R3 = r3; + jump StgReturn [R1]; +} + +stg_block_atomicreadmvar /* mvar passed in R1 */ +{ + Sp_adj(-2); + Sp(1) = R1; + Sp(0) = stg_block_atomicreadmvar_info; + R3 = R1; // mvar communicated to stg_block_atomicreadmvar_finally in R3 + BLOCK_BUT_FIRST(stg_block_atomicreadmvar_finally); +} + INFO_TABLE_RET( stg_block_putmvar, RET_SMALL, W_ info_ptr, P_ mvar, P_ val ) return () |