summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2012-08-07 14:44:46 +0100
committerSimon Marlow <marlowsd@gmail.com>2012-08-07 15:50:39 +0100
commit396f09031b363bf2f0d2afa28a86e67a0628a696 (patch)
tree23cf23e48daad91181b68e527bba7212b8c74605 /rts
parent69cda9ef2a54753ee43dda0c3d0ecec21bde8b85 (diff)
downloadhaskell-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.c35
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)