From 2781d68c5d94fd87435d6316c2d4118171e97b14 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Fri, 27 Sep 2019 01:39:15 +0000 Subject: rts: Annotate benign race in waitForCapability --- rts/Capability.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'rts/Capability.c') diff --git a/rts/Capability.c b/rts/Capability.c index 6ab8f40dfa..07141009a1 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -748,6 +748,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 * @@ -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 -- cgit v1.2.1