summaryrefslogtreecommitdiff
path: root/rts/Capability.c
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-11-22 11:58:32 -0500
committerBen Gamari <ben@smart-cactus.org>2020-10-24 21:02:22 -0400
commit01d9552509a94d1bd1a717f1730b1c513bf7fea8 (patch)
tree341d97e220140b0d796ac07daf4f631d05eab700 /rts/Capability.c
parent5a98dfcae41b79bed912521d1eeb2cbc09f0742b (diff)
downloadhaskell-01d9552509a94d1bd1a717f1730b1c513bf7fea8.tar.gz
Fix #17289
Diffstat (limited to 'rts/Capability.c')
-rw-r--r--rts/Capability.c26
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
}