summaryrefslogtreecommitdiff
path: root/rts/Capability.c
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-09-27 01:39:15 +0000
committerBen Gamari <ben@smart-cactus.org>2020-10-24 21:00:36 -0400
commit2781d68c5d94fd87435d6316c2d4118171e97b14 (patch)
treeb21bb78704eeed08cdeb26d47a2827cc55fc9701 /rts/Capability.c
parent16b136b0c3c79833a1e35305f9c5d1b0511eda9c (diff)
downloadhaskell-2781d68c5d94fd87435d6316c2d4118171e97b14.tar.gz
rts: Annotate benign race in waitForCapability
Diffstat (limited to 'rts/Capability.c')
-rw-r--r--rts/Capability.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/rts/Capability.c b/rts/Capability.c
index 6ab8f40dfa..07141009a1 100644
--- a/rts/Capability.c
+++ b/rts/Capability.c
@@ -749,6 +749,22 @@ static Capability * waitForReturnCapability (Task *task)
#if defined(THREADED_RTS)
/* ----------------------------------------------------------------------------
+ * capability_is_busy (Capability *cap)
+ *
+ * A predicate for determining whether the given Capability is currently running
+ * a Task. This can be safely called without holding the Capability's lock
+ * although the result may be inaccurate if it races with the scheduler.
+ * Consequently there is a TSAN suppression for it.
+ *
+ * ------------------------------------------------------------------------- */
+static bool capability_is_busy(const Capability * cap)
+{
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->running_task, "capability_is_busy");
+ return cap->running_task != NULL;
+}
+
+
+/* ----------------------------------------------------------------------------
* find_capability_for_task
*
* Given a Task, identify a reasonable Capability to run it on. We try to
@@ -765,7 +781,11 @@ static Capability * find_capability_for_task(const Task * task)
} else {
// Try last_free_capability first
Capability *cap = last_free_capability[task->node];
- if (cap->running_task == NULL) {
+
+ // N.B. There is a data race here since we are loking at
+ // cap->running_task without taking cap->lock. However, this is
+ // benign since the result is merely guiding our search heuristic.
+ if (!capability_is_busy(cap)) {
return cap;
} else {
// The last_free_capability is already busy, search for a free