diff options
author | Ben Gamari <bgamari.foss@gmail.com> | 2013-01-28 11:15:08 -0500 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2013-01-30 10:50:14 +0000 |
commit | a23661d242e8dd55007c4aee8a053f35de7705bd (patch) | |
tree | e55bb371b52998e870a252de8768aaf4d1de6849 /rts/STM.c | |
parent | 658817bf1b44e9be8a3857c09aae086bef937720 (diff) | |
download | haskell-a23661d242e8dd55007c4aee8a053f35de7705bd.tar.gz |
STM: Only wake up once
Previously, threads blocked on an STM retry would be sent a wakeup
message each time an unpark was requested. This could result in the
accumulation of a large number of wake-up messages, which would slow
wake-up once the sleeping thread is finally scheduled.
Here, we introduce a new closure type, STM_AWOKEN, which marks a TSO
which has been sent a wake-up message, allowing us to send only one
wakeup.
Diffstat (limited to 'rts/STM.c')
-rw-r--r-- | rts/STM.c | 16 |
1 files changed, 11 insertions, 5 deletions
@@ -380,13 +380,19 @@ static void unpark_tso(Capability *cap, StgTSO *tso) { // Unblocking a TSO from BlockedOnSTM is done under the TSO lock, // to avoid multiple CPUs unblocking the same TSO, and also to - // synchronise with throwTo(). + // synchronise with throwTo(). The first time the TSO is unblocked + // we mark this fact by setting block_info.closure == STM_AWOKEN. + // This way we can avoid sending further wakeup messages in the + // future. lockTSO(tso); - if (tso -> why_blocked == BlockedOnSTM) { - TRACE("unpark_tso on tso=%p", tso); - tryWakeupThread(cap,tso); + if (tso->why_blocked == BlockedOnSTM && tso->block_info.closure == STM_AWOKEN) { + TRACE("unpark_tso already woken up tso=%p", tso); + } else if (tso -> why_blocked == BlockedOnSTM) { + TRACE("unpark_tso on tso=%p", tso); + tso->block_info.closure = STM_AWOKEN; + tryWakeupThread(cap,tso); } else { - TRACE("spurious unpark_tso on tso=%p", tso); + TRACE("spurious unpark_tso on tso=%p", tso); } unlockTSO(tso); } |