diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-11-22 11:58:32 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-10-24 21:02:22 -0400 |
commit | 01d9552509a94d1bd1a717f1730b1c513bf7fea8 (patch) | |
tree | 341d97e220140b0d796ac07daf4f631d05eab700 | |
parent | 5a98dfcae41b79bed912521d1eeb2cbc09f0742b (diff) | |
download | haskell-01d9552509a94d1bd1a717f1730b1c513bf7fea8.tar.gz |
Fix #17289
-rw-r--r-- | rts/Capability.c | 26 | ||||
-rw-r--r-- | rts/Timer.c | 4 |
2 files changed, 19 insertions, 11 deletions
diff --git a/rts/Capability.c b/rts/Capability.c index 181075b963..4cbe35d34d 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -410,36 +410,44 @@ void moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS) { #if defined(THREADED_RTS) - uint32_t i; - Capability **old_capabilities = capabilities; + Capability **new_capabilities = stgMallocBytes(to * sizeof(Capability*), "moreCapabilities"); - capabilities = stgMallocBytes(to * sizeof(Capability*), "moreCapabilities"); + // We must disable the timer while we do this since the tick handler may + // call contextSwitchAllCapabilities, which may see the capabilities array + // as we free it. The alternative would be to protect the capabilities + // array with a lock but this seems more expensive than necessary. + // See #17289. + stopTimer(); if (to == 1) { // THREADED_RTS must work on builds that don't have a mutable // BaseReg (eg. unregisterised), so in this case // capabilities[0] must coincide with &MainCapability. - capabilities[0] = &MainCapability; + new_capabilities[0] = &MainCapability; initCapability(&MainCapability, 0); } else { - for (i = 0; i < to; i++) { + for (uint32_t i = 0; i < to; i++) { if (i < from) { - capabilities[i] = old_capabilities[i]; + new_capabilities[i] = capabilities[i]; } else { - capabilities[i] = stgMallocBytes(sizeof(Capability), - "moreCapabilities"); - initCapability(capabilities[i], i); + new_capabilities[i] = stgMallocBytes(sizeof(Capability), + "moreCapabilities"); + initCapability(new_capabilities[i], i); } } } debugTrace(DEBUG_sched, "allocated %d more capabilities", to - from); + Capability **old_capabilities = ACQUIRE_LOAD(&capabilities); + RELEASE_STORE(&capabilities, new_capabilities); if (old_capabilities != NULL) { stgFree(old_capabilities); } + + startTimer(); #endif } diff --git a/rts/Timer.c b/rts/Timer.c index 63854d7dda..fa7679e80c 100644 --- a/rts/Timer.c +++ b/rts/Timer.c @@ -102,7 +102,7 @@ handle_tick(int unused STG_UNUSED) { handleProfTick(); if (RtsFlags.ConcFlags.ctxtSwitchTicks > 0 - && RELAXED_LOAD(&timer_disabled) == 0) + && SEQ_CST_LOAD(&timer_disabled) == 0) { ticks_to_ctxt_switch--; if (ticks_to_ctxt_switch <= 0) { @@ -166,7 +166,7 @@ initTimer(void) if (RtsFlags.MiscFlags.tickInterval != 0) { initTicker(RtsFlags.MiscFlags.tickInterval, handle_tick); } - RELAXED_STORE(&timer_disabled, 1); + SEQ_CST_STORE(&timer_disabled, 1); } void |