summaryrefslogtreecommitdiff
path: root/rts/Messages.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-03-29 14:45:21 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-03-29 14:45:21 +0000
commit2726a2f10256710cc6ed80b1098cb32e121e1be7 (patch)
tree81eef196c77c6a7f4581547202e664f38cc70882 /rts/Messages.c
parent4b7fdaa8617e1fadc6175d2400d11fa1fc062c03 (diff)
downloadhaskell-2726a2f10256710cc6ed80b1098cb32e121e1be7.tar.gz
Move a thread to the front of the run queue when another thread blocks on it
This fixes #3838, and was made possible by the new BLACKHOLE infrastructure. To allow reording of the run queue I had to make it doubly-linked, which entails some extra trickiness with regard to GC write barriers and suchlike.
Diffstat (limited to 'rts/Messages.c')
-rw-r--r--rts/Messages.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/rts/Messages.c b/rts/Messages.c
index 6a7c64de58..ae5d5d1abc 100644
--- a/rts/Messages.c
+++ b/rts/Messages.c
@@ -244,7 +244,21 @@ loop:
bq->link = owner->bq;
owner->bq = bq;
dirty_TSO(cap, owner); // we modified owner->bq
-
+
+ // If the owner of the blackhole is currently runnable, then
+ // bump it to the front of the run queue. This gives the
+ // blocked-on thread a little boost which should help unblock
+ // this thread, and may avoid a pile-up of other threads
+ // becoming blocked on the same BLACKHOLE (#3838).
+ //
+ // NB. we check to make sure that the owner is not the same as
+ // the current thread, since in that case it will not be on
+ // the run queue.
+ if (owner->why_blocked == NotBlocked && owner->id != msg->tso->id) {
+ removeFromRunQueue(cap, owner);
+ pushOnRunQueue(cap,owner);
+ }
+
// point to the BLOCKING_QUEUE from the BLACKHOLE
write_barrier(); // make the BQ visible
((StgInd*)bh)->indirectee = (StgClosure *)bq;
@@ -280,12 +294,18 @@ loop:
if (info == &stg_BLOCKING_QUEUE_CLEAN_info) {
bq->header.info = &stg_BLOCKING_QUEUE_DIRTY_info;
- recordClosureMutated(cap,bq);
+ recordClosureMutated(cap,(StgClosure*)bq);
}
debugTraceCap(DEBUG_sched, cap, "thread %d blocked on thread %d",
(lnat)msg->tso->id, (lnat)owner->id);
+ // See above, #3838
+ if (owner->why_blocked == NotBlocked && owner->id != msg->tso->id) {
+ removeFromRunQueue(cap, owner);
+ pushOnRunQueue(cap,owner);
+ }
+
return 1; // blocked
}