summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-09-27 01:50:37 +0000
committerBen Gamari <ben@smart-cactus.org>2020-10-24 21:00:37 -0400
commitf88710185acc0e02b334b96004f4b8fae38c5eb9 (patch)
tree72e5e494575f6c9b23ba64553ec3bed7f4cc94ad
parent8d2b3c3d1fcb9009b6dfcce85777e04bcec9d219 (diff)
downloadhaskell-f88710185acc0e02b334b96004f4b8fae38c5eb9.tar.gz
rts/Schedule: Eliminate data races on recent_activity
We cannot safely use relaxed atomics here.
-rw-r--r--rts/Capability.c2
-rw-r--r--rts/Schedule.c14
-rw-r--r--rts/Timer.c8
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