summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosef Svenningsson <josef.svenningsson@gmail.com>2008-10-10 15:03:22 +0000
committerJosef Svenningsson <josef.svenningsson@gmail.com>2008-10-10 15:03:22 +0000
commita970a3775856642e6d3690b5421e7dcb3e420d36 (patch)
tree80c7621116e716f16c093a7f59ca5638fe0c8fb1
parentb69843467459d43168519ced8d0cf45227c4c7be (diff)
downloadhaskell-a970a3775856642e6d3690b5421e7dcb3e420d36.tar.gz
When waking up thread blocked on TVars, wake oldest first (#2319)
StgTVarWatchQueue contains the threads blocked on a TVar in order youngest first. The list has to be traversed backwards to unpark the threads oldest first. This improves the fairness when using STM in some situations.
-rw-r--r--rts/STM.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/rts/STM.c b/rts/STM.c
index c271a25d3c..b5dcc54884 100644
--- a/rts/STM.c
+++ b/rts/STM.c
@@ -389,9 +389,17 @@ static void unpark_tso(Capability *cap, StgTSO *tso) {
static void unpark_waiters_on(Capability *cap, StgTVar *s) {
StgTVarWatchQueue *q;
TRACE("unpark_waiters_on tvar=%p", s);
- for (q = s -> first_watch_queue_entry;
- q != END_STM_WATCH_QUEUE;
+ StgTVarWatchQueue *trail;
+ // unblock TSOs in reverse order, to be a bit fairer (#2319)
+ for (q = s -> first_watch_queue_entry, trail = q;
+ q != END_STM_WATCH_QUEUE;
q = q -> next_queue_entry) {
+ trail = q;
+ }
+ q = trail;
+ for (;
+ q != END_STM_WATCH_QUEUE;
+ q = q -> prev_queue_entry) {
if (watcher_is_tso(q)) {
unpark_tso(cap, (StgTSO *)(q -> closure));
}