diff options
author | Simon Marlow <marlowsd@gmail.com> | 2012-08-07 14:44:46 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2012-08-07 15:50:39 +0100 |
commit | 396f09031b363bf2f0d2afa28a86e67a0628a696 (patch) | |
tree | 23cf23e48daad91181b68e527bba7212b8c74605 /rts | |
parent | 69cda9ef2a54753ee43dda0c3d0ecec21bde8b85 (diff) | |
download | haskell-396f09031b363bf2f0d2afa28a86e67a0628a696.tar.gz |
Fix a bug in the handling of recent_activity
The problem occurred when the idle GC was turned off with +RTS -I0.
Then the scheduler would go into the state ACTIVITY_DONE_GC directly
without doing a GC, and a subsequent GC would put it back to
ACTIVITY_YES but without turning the timer back on. Instead if the GC
finds the state is ACTIVITY_DONE_GC it should leave it there.
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Schedule.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c index dee71c4676..310e68e629 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -1658,21 +1658,30 @@ delete_threads_and_gc: traceSparkCounters(cap); - if (recent_activity == ACTIVITY_INACTIVE && force_major) - { - // We are doing a GC because the system has been idle for a - // timeslice and we need to check for deadlock. Record the - // fact that we've done a GC and turn off the timer signal; - // it will get re-enabled if we run any threads after the GC. - recent_activity = ACTIVITY_DONE_GC; - stopTimer(); - } - else - { + switch (recent_activity) { + case ACTIVITY_INACTIVE: + if (force_major) { + // We are doing a GC because the system has been idle for a + // timeslice and we need to check for deadlock. Record the + // fact that we've done a GC and turn off the timer signal; + // it will get re-enabled if we run any threads after the GC. + recent_activity = ACTIVITY_DONE_GC; + stopTimer(); + break; + } + // fall through... + + case ACTIVITY_MAYBE_NO: // the GC might have taken long enough for the timer to set - // recent_activity = ACTIVITY_INACTIVE, but we aren't - // necessarily deadlocked: + // recent_activity = ACTIVITY_MAYBE_NO or ACTIVITY_INACTIVE, + // but we aren't necessarily deadlocked: recent_activity = ACTIVITY_YES; + break; + + case ACTIVITY_DONE_GC: + // If we are actually active, the scheduler will reset the + // recent_activity flag and re-enable the timer. + break; } #if defined(THREADED_RTS) |