summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2011-02-02 11:49:07 +0000
committerSimon Marlow <marlowsd@gmail.com>2011-02-02 11:49:07 +0000
commitc226846642a2201762ee34f6f71b42f13bc46629 (patch)
tree57c61697fb3f177597f07c17357b8879d4b12a70 /rts
parent26f4bfc82f2b2359259578e9c54d476fc2de650f (diff)
downloadhaskell-c226846642a2201762ee34f6f71b42f13bc46629.tar.gz
scheduleProcessInbox: use non-blocking acquire, and take the whole queue
This is an improvement from my GC branch, that helps performance for intensive message-passing communication between Capabilities.
Diffstat (limited to 'rts')
-rw-r--r--rts/Schedule.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c
index 4343a149cc..7c945e0ec3 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -951,14 +951,38 @@ static void
scheduleProcessInbox (Capability *cap USED_IF_THREADS)
{
#if defined(THREADED_RTS)
- Message *m;
+ Message *m, *next;
+ int r;
while (!emptyInbox(cap)) {
- ACQUIRE_LOCK(&cap->lock);
+ if (cap->r.rCurrentNursery->link == NULL ||
+ g0->n_new_large_words >= large_alloc_lim) {
+ scheduleDoGC(cap, cap->running_task, rtsFalse);
+ }
+
+ // don't use a blocking acquire; if the lock is held by
+ // another thread then just carry on. This seems to avoid
+ // getting stuck in a message ping-pong situation with other
+ // processors. We'll check the inbox again later anyway.
+ //
+ // We should really use a more efficient queue data structure
+ // here. The trickiness is that we must ensure a Capability
+ // never goes idle if the inbox is non-empty, which is why we
+ // use cap->lock (cap->lock is released as the last thing
+ // before going idle; see Capability.c:releaseCapability()).
+ r = TRY_ACQUIRE_LOCK(&cap->lock);
+ if (r != 0) return;
+
m = cap->inbox;
- cap->inbox = m->link;
+ cap->inbox = (Message*)END_TSO_QUEUE;
+
RELEASE_LOCK(&cap->lock);
- executeMessage(cap, (Message *)m);
+
+ while (m != (Message*)END_TSO_QUEUE) {
+ next = m->link;
+ executeMessage(cap, m);
+ m = next;
+ }
}
#endif
}