diff options
author | Simon Marlow <marlowsd@gmail.com> | 2011-02-02 11:49:07 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2011-02-02 11:49:07 +0000 |
commit | c226846642a2201762ee34f6f71b42f13bc46629 (patch) | |
tree | 57c61697fb3f177597f07c17357b8879d4b12a70 /rts | |
parent | 26f4bfc82f2b2359259578e9c54d476fc2de650f (diff) | |
download | haskell-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.c | 32 |
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 } |