From 80c3fa5476bbdab479b57e892001b3259b5b3537 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 2 Jan 2018 16:00:58 +0200 Subject: Fix data race (tsan) bug --- build2/scheduler.cxx | 10 ++++++---- build2/scheduler.hxx | 17 +++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/build2/scheduler.cxx b/build2/scheduler.cxx index cd621bc..e6a0bc6 100644 --- a/build2/scheduler.cxx +++ b/build2/scheduler.cxx @@ -186,8 +186,8 @@ namespace build2 try { shutdown (); } catch (system_error&) {} } - void scheduler:: - wait_idle () + auto scheduler:: + wait_idle () -> lock { lock l (mutex_); @@ -200,6 +200,8 @@ namespace build2 this_thread::yield (); l.lock (); } + + return l; } size_t scheduler:: @@ -319,7 +321,7 @@ namespace build2 // The scheduler must not be active though some threads might still be // comming off from finishing a task. So we busy-wait for them. // - wait_idle (); + lock l (wait_idle ()); max_active_ = max_active; } @@ -411,7 +413,7 @@ namespace build2 // comming off from finishing a task and trying to report progress. So we // busy-wait for them (also in ~monitor_guard()). // - wait_idle (); + lock l (wait_idle ()); monitor_count_ = &c; monitor_tshold_.store (t, memory_order_relaxed); diff --git a/build2/scheduler.hxx b/build2/scheduler.hxx index 20e5128..4880392 100644 --- a/build2/scheduler.hxx +++ b/build2/scheduler.hxx @@ -256,7 +256,7 @@ namespace build2 { if (s_ != nullptr) { - s_->wait_idle (); // See monitor() for details. + lock l (s_->wait_idle ()); // See monitor() for details. s_->monitor_count_ = nullptr; s_->monitor_func_ = nullptr; } @@ -300,12 +300,6 @@ namespace build2 task_queue_ = nullptr; } - // Assuming all the task have been executed, busy-wait for all the threads - // to become idle. Normally you don't need to call this function directly. - // - void - wait_idle (); - // Return the number of hardware threads or 0 if unable to determine. // static size_t @@ -324,9 +318,16 @@ namespace build2 size_t shard_size (size_t mul = 1, size_t div = 1) const; - private: + // Assuming all the task have been executed, busy-wait for all the threads + // to become idle. Return the lock over the scheduler mutex. Normally you + // don't need to call this function directly. + // using lock = std::unique_lock; + lock + wait_idle (); + + private: void activate_helper (lock&); -- cgit v1.1