diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-08-07 07:56:23 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2019-08-07 07:56:23 +0200 |
commit | 20ce40e34faf6b08f8c3bb9a149a3975fd4403cc (patch) | |
tree | ce92a45a07399535ed6e3e36f020896fa9fa519f /libbuild2 | |
parent | 0592557e49cc7d6a2da2b5d9f5aaaeefbfcf7248 (diff) |
Tighten deadlock monitor notification logic
Diffstat (limited to 'libbuild2')
-rw-r--r-- | libbuild2/scheduler.cxx | 49 | ||||
-rw-r--r-- | libbuild2/scheduler.hxx | 2 |
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 |