diff options
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r-- | rts/PrimOps.cmm | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm index 7767ead2d8..a6b60ae1cc 100644 --- a/rts/PrimOps.cmm +++ b/rts/PrimOps.cmm @@ -1827,9 +1827,16 @@ loop: // There are readMVar/takeMVar(s) waiting: wake up the first one tso = StgMVarTSOQueue_tso(q); - StgMVar_head(mvar) = StgMVarTSOQueue_link(q); - if (StgMVar_head(mvar) == stg_END_TSO_QUEUE_closure) { + q = StgMVarTSOQueue_link(q); + StgMVar_head(mvar) = q; + if (q == stg_END_TSO_QUEUE_closure) { StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure; + } else { + if (info == stg_MVAR_CLEAN_info) { + // Resolve #18919. + ccall dirty_MVAR(BaseReg "ptr", mvar "ptr", + StgMVar_value(mvar) "ptr"); + } } ASSERT(StgTSO_block_info(tso) == mvar); @@ -1854,10 +1861,8 @@ loop: // If it was a readMVar, then we can still do work, // so loop back. (XXX: This could take a while) - if (why_blocked == BlockedOnMVarRead) { - q = StgMVarTSOQueue_link(q); + if (why_blocked == BlockedOnMVarRead) goto loop; - } ASSERT(why_blocked == BlockedOnMVar); @@ -1912,9 +1917,16 @@ loop: // There are takeMVar(s) waiting: wake up the first one tso = StgMVarTSOQueue_tso(q); - StgMVar_head(mvar) = StgMVarTSOQueue_link(q); - if (StgMVar_head(mvar) == stg_END_TSO_QUEUE_closure) { + q = StgMVarTSOQueue_link(q); + StgMVar_head(mvar) = q; + if (q == stg_END_TSO_QUEUE_closure) { StgMVar_tail(mvar) = stg_END_TSO_QUEUE_closure; + } else { + if (info == stg_MVAR_CLEAN_info) { + // Resolve #18919. + ccall dirty_MVAR(BaseReg "ptr", mvar "ptr", + StgMVar_value(mvar) "ptr"); + } } ASSERT(StgTSO_block_info(tso) == mvar); @@ -1939,10 +1951,8 @@ loop: // If it was a readMVar, then we can still do work, // so loop back. (XXX: This could take a while) - if (why_blocked == BlockedOnMVarRead) { - q = StgMVarTSOQueue_link(q); + if (why_blocked == BlockedOnMVarRead) goto loop; - } ASSERT(why_blocked == BlockedOnMVar); |