diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-09-27 00:49:15 +0000 |
---|---|---|
committer | Moritz Angermann <moritz.angermann@gmail.com> | 2020-09-18 07:33:40 +0000 |
commit | 2d827886bbfbc6218084a35627292484695fff19 (patch) | |
tree | fb108ae52bac385b0c25278044e0d8b010e93934 | |
parent | 1d9ac2fcf7f3a35e4ec6493cf3a1793f4c2710d5 (diff) | |
download | haskell-2d827886bbfbc6218084a35627292484695fff19.tar.gz |
rts: Factor out logic to identify a good capability for running a task
Not only does this make the control flow a bit clearer but it also
allows us to add a TSAN suppression on this logic, which requires
(harmless) data races.
-rw-r--r-- | rts/Capability.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/rts/Capability.c b/rts/Capability.c index 7f6d66a37d..ee29db9e84 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -740,6 +740,46 @@ static Capability * waitForReturnCapability (Task *task) #endif /* THREADED_RTS */ +#if defined(THREADED_RTS) + +/* ---------------------------------------------------------------------------- + * find_capability_for_task + * + * Given a Task, identify a reasonable Capability to run it on. We try to + * find an idle capability if possible. + * + * ------------------------------------------------------------------------- */ + +static Capability * find_capability_for_task(const Task * task) +{ + if (task->preferred_capability != -1) { + // Does the task have a preferred capability? If so, use it + return capabilities[task->preferred_capability % + enabled_capabilities]; + } else { + // Try last_free_capability first + Capability *cap = last_free_capability[task->node]; + if (cap->running_task == NULL) { + return cap; + } else { + // The last_free_capability is already busy, search for a free + // capability on this node. + for (uint32_t i = task->node; i < enabled_capabilities; + i += n_numa_nodes) { + // visits all the capabilities on this node, because + // cap[i]->node == i % n_numa_nodes + if (!capabilities[i]->running_task) { + return capabilities[i]; + } + } + + // Can't find a free one, use last_free_capability. + return last_free_capability[task->node]; + } + } +} +#endif /* THREADED_RTS */ + /* ---------------------------------------------------------------------------- * waitForCapability (Capability **pCap, Task *task) * @@ -760,38 +800,13 @@ void waitForCapability (Capability **pCap, Task *task) *pCap = &MainCapability; #else - uint32_t i; Capability *cap = *pCap; if (cap == NULL) { - if (task->preferred_capability != -1) { - cap = capabilities[task->preferred_capability % - enabled_capabilities]; - } else { - // Try last_free_capability first - cap = last_free_capability[task->node]; - if (cap->running_task) { - // Otherwise, search for a free capability on this node. - cap = NULL; - for (i = task->node; i < enabled_capabilities; - i += n_numa_nodes) { - // visits all the capabilities on this node, because - // cap[i]->node == i % n_numa_nodes - if (!capabilities[i]->running_task) { - cap = capabilities[i]; - break; - } - } - if (cap == NULL) { - // Can't find a free one, use last_free_capability. - cap = last_free_capability[task->node]; - } - } - } + cap = find_capability_for_task(task); // record the Capability as the one this Task is now assocated with. task->cap = cap; - } else { ASSERT(task->cap == cap); } |