aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-08-07 07:56:23 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-08-07 07:56:23 +0200
commit20ce40e34faf6b08f8c3bb9a149a3975fd4403cc (patch)
treece92a45a07399535ed6e3e36f020896fa9fa519f
parent0592557e49cc7d6a2da2b5d9f5aaaeefbfcf7248 (diff)
Tighten deadlock monitor notification logic
-rw-r--r--libbuild2/scheduler.cxx49
-rw-r--r--libbuild2/scheduler.hxx2
2 files changed, 27 insertions, 24 deletions
diff --git a/libbuild2/scheduler.cxx b/libbuild2/scheduler.cxx
index e008fd6..b261a82 100644
--- a/libbuild2/scheduler.cxx
+++ b/libbuild2/scheduler.cxx
@@ -120,10 +120,9 @@ namespace build2
{
ready_condv_.notify_one ();
}
- else if (queued_task_count_.load (std::memory_order_consume) != 0)
- {
- activate_helper (l);
- }
+ else if (queued_task_count_.load (std::memory_order_consume) != 0 &&
+ activate_helper (l))
+ ;
else if (active_ == 0 && external_ == 0)
{
// Note that we tried to handle this directly in this thread but that
@@ -521,29 +520,33 @@ namespace build2
return monitor_guard (this);
}
- void scheduler::
+ bool scheduler::
activate_helper (lock& l)
{
- if (!shutdown_)
+ if (shutdown_)
+ return false;
+
+ if (idle_ != 0)
{
- if (idle_ != 0)
- {
- idle_condv_.notify_one ();
- }
- //
- // Ignore the max_threads value if we have queued tasks but no active
- // threads. This means everyone is waiting for something to happen but
- // nobody is doing anything (e.g., working the queues). This, for
- // example, can happen if a thread waits for a task that is in its queue
- // but is below the mark.
- //
- else if (init_active_ + helpers_ < max_threads_ ||
- (active_ == 0 &&
- queued_task_count_.load (memory_order_consume) != 0))
- {
- create_helper (l);
- }
+ idle_condv_.notify_one ();
+ }
+ //
+ // Ignore the max_threads value if we have queued tasks but no active
+ // threads. This means everyone is waiting for something to happen but
+ // nobody is doing anything (e.g., working the queues). This, for
+ // example, can happen if a thread waits for a task that is in its queue
+ // but is below the mark.
+ //
+ else if (init_active_ + helpers_ < max_threads_ ||
+ (active_ == 0 &&
+ queued_task_count_.load (memory_order_consume) != 0))
+ {
+ create_helper (l);
}
+ else
+ return false;
+
+ return true;
}
void scheduler::
diff --git a/libbuild2/scheduler.hxx b/libbuild2/scheduler.hxx
index 99b27c9..0107753 100644
--- a/libbuild2/scheduler.hxx
+++ b/libbuild2/scheduler.hxx
@@ -350,7 +350,7 @@ namespace build2
wait_idle ();
private:
- void
+ bool
activate_helper (lock&);
void