summaryrefslogtreecommitdiff
path: root/rts/STM.c
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2013-01-28 11:15:08 -0500
committerSimon Marlow <marlowsd@gmail.com>2013-01-30 10:50:14 +0000
commita23661d242e8dd55007c4aee8a053f35de7705bd (patch)
treee55bb371b52998e870a252de8768aaf4d1de6849 /rts/STM.c
parent658817bf1b44e9be8a3857c09aae086bef937720 (diff)
downloadhaskell-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.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/rts/STM.c b/rts/STM.c
index 62ced25f65..7400d57bab 100644
--- a/rts/STM.c
+++ b/rts/STM.c
@@ -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);
}