diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-09-27 01:50:37 +0000 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-10-24 21:00:37 -0400 |
commit | f88710185acc0e02b334b96004f4b8fae38c5eb9 (patch) | |
tree | 72e5e494575f6c9b23ba64553ec3bed7f4cc94ad | |
parent | 8d2b3c3d1fcb9009b6dfcce85777e04bcec9d219 (diff) | |
download | haskell-f88710185acc0e02b334b96004f4b8fae38c5eb9.tar.gz |
rts/Schedule: Eliminate data races on recent_activity
We cannot safely use relaxed atomics here.
-rw-r--r-- | rts/Capability.c | 2 | ||||
-rw-r--r-- | rts/Schedule.c | 14 | ||||
-rw-r--r-- | rts/Timer.c | 8 |
3 files changed, 12 insertions, 12 deletions
diff --git a/rts/Capability.c b/rts/Capability.c index 5ebe6c8b46..3031d283c4 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -85,7 +85,7 @@ STATIC_INLINE bool globalWorkToDo (void) { return RELAXED_LOAD(&sched_state) >= SCHED_INTERRUPTING - || recent_activity == ACTIVITY_INACTIVE; // need to check for deadlock + || RELAXED_LOAD(&recent_activity) == ACTIVITY_INACTIVE; // need to check for deadlock } #endif diff --git a/rts/Schedule.c b/rts/Schedule.c index a9ae7a4ce4..e8bb9c1bf0 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -440,7 +440,7 @@ run_thread: dirty_TSO(cap,t); dirty_STACK(cap,t->stackobj); - switch (recent_activity) + switch (SEQ_CST_LOAD(&recent_activity)) { case ACTIVITY_DONE_GC: { // ACTIVITY_DONE_GC means we turned off the timer signal to @@ -461,7 +461,7 @@ run_thread: // wakeUpRts(). break; default: - recent_activity = ACTIVITY_YES; + SEQ_CST_STORE(&recent_activity, ACTIVITY_YES); } traceEventRunThread(cap, t); @@ -939,7 +939,7 @@ scheduleDetectDeadlock (Capability **pcap, Task *task) * we won't eagerly start a full GC just because we don't have * any threads to run currently. */ - if (recent_activity != ACTIVITY_INACTIVE) return; + if (SEQ_CST_LOAD(&recent_activity) != ACTIVITY_INACTIVE) return; #endif if (task->incall->tso && task->incall->tso->why_blocked == BlockedOnIOCompletion) return; @@ -1880,14 +1880,14 @@ delete_threads_and_gc: traceSparkCounters(cap); - switch (recent_activity) { + switch (SEQ_CST_LOAD(&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; + SEQ_CST_STORE(&recent_activity, ACTIVITY_DONE_GC); #if !defined(PROFILING) stopTimer(); #endif @@ -1899,7 +1899,7 @@ delete_threads_and_gc: // the GC might have taken long enough for the timer to set // recent_activity = ACTIVITY_MAYBE_NO or ACTIVITY_INACTIVE, // but we aren't necessarily deadlocked: - recent_activity = ACTIVITY_YES; + SEQ_CST_STORE(&recent_activity, ACTIVITY_YES); break; case ACTIVITY_DONE_GC: @@ -2701,7 +2701,7 @@ initScheduler(void) #endif sched_state = SCHED_RUNNING; - recent_activity = ACTIVITY_YES; + SEQ_CST_STORE(&recent_activity, ACTIVITY_YES); /* Initialise the mutex and condition variables used by diff --git a/rts/Timer.c b/rts/Timer.c index 057cffc7c9..990eba6b05 100644 --- a/rts/Timer.c +++ b/rts/Timer.c @@ -106,16 +106,16 @@ handle_tick(int unused STG_UNUSED) * for threads that are deadlocked. However, ensure we wait * at least interIdleGCWait (+RTS -Iw) between idle GCs. */ - switch (recent_activity) { + switch (SEQ_CST_LOAD(&recent_activity)) { case ACTIVITY_YES: - recent_activity = ACTIVITY_MAYBE_NO; + SEQ_CST_STORE(&recent_activity, ACTIVITY_MAYBE_NO); idle_ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime / RtsFlags.MiscFlags.tickInterval; break; case ACTIVITY_MAYBE_NO: if (idle_ticks_to_gc == 0 && inter_gc_ticks_to_gc == 0) { if (RtsFlags.GcFlags.doIdleGC) { - recent_activity = ACTIVITY_INACTIVE; + SEQ_CST_STORE(&recent_activity, ACTIVITY_INACTIVE); inter_gc_ticks_to_gc = RtsFlags.GcFlags.interIdleGCWait / RtsFlags.MiscFlags.tickInterval; #if defined(THREADED_RTS) @@ -124,7 +124,7 @@ handle_tick(int unused STG_UNUSED) // the GC. #endif } else { - recent_activity = ACTIVITY_DONE_GC; + SEQ_CST_STORE(&recent_activity, ACTIVITY_DONE_GC); // disable timer signals (see #1623, #5991, #9105) // but only if we're not profiling (e.g. passed -h or -p RTS // flags). If we are profiling we need to keep the timer active |