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 /rts/Capability.c | |
parent | 5a98dfcae41b79bed912521d1eeb2cbc09f0742b (diff) | |
download | haskell-01d9552509a94d1bd1a717f1730b1c513bf7fea8.tar.gz |
Fix #17289
Diffstat (limited to 'rts/Capability.c')
-rw-r--r-- | rts/Capability.c | 26 |
1 files changed, 17 insertions, 9 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 } |