aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/Parallel.cpp
diff options
context:
space:
mode:
authorYaxun (Sam) Liu <yaxun.liu@amd.com>2025-10-03 10:35:03 -0400
committerYaxun (Sam) Liu <yaxun.liu@amd.com>2025-10-03 10:35:03 -0400
commitf8f6c0b6ecb9d87ead48246d4fadf6048207375d (patch)
tree4ebcbae83912eae36dad83a045ed3060aca25845 /llvm/lib/Support/Parallel.cpp
parentc75ae01233b0965d48e3770160119c162eb5c2ee (diff)
downloadllvm-f8f6c0b6ecb9d87ead48246d4fadf6048207375d.zip
llvm-f8f6c0b6ecb9d87ead48246d4fadf6048207375d.tar.gz
llvm-f8f6c0b6ecb9d87ead48246d4fadf6048207375d.tar.bz2
Revert "[LLVM] Add GNU make jobserver support (#145131)"
revert this patch due to failure in unittests/Support, e.g. https://lab.llvm.org/buildbot/#/builders/33/builds/24178/steps/6/logs/FAIL__LLVM-Unit__SupportTests_61 This reverts commit ffc503edd0a2d07121232fe204e480fc29631a90.
Diffstat (limited to 'llvm/lib/Support/Parallel.cpp')
-rw-r--r--llvm/lib/Support/Parallel.cpp98
1 files changed, 11 insertions, 87 deletions
diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp
index 8e0c724..3ac6fc7 100644
--- a/llvm/lib/Support/Parallel.cpp
+++ b/llvm/lib/Support/Parallel.cpp
@@ -7,17 +7,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Parallel.h"
-#include "llvm/ADT/ScopeExit.h"
#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/ExponentialBackoff.h"
-#include "llvm/Support/Jobserver.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Threading.h"
#include <atomic>
#include <future>
-#include <memory>
-#include <mutex>
#include <thread>
#include <vector>
@@ -54,9 +49,6 @@ public:
class ThreadPoolExecutor : public Executor {
public:
explicit ThreadPoolExecutor(ThreadPoolStrategy S) {
- if (S.UseJobserver)
- TheJobserver = JobserverClient::getInstance();
-
ThreadCount = S.compute_thread_count();
// Spawn all but one of the threads in another thread as spawning threads
// can take a while.
@@ -77,10 +69,6 @@ public:
});
}
- // To make sure the thread pool executor can only be created with a parallel
- // strategy.
- ThreadPoolExecutor() = delete;
-
void stop() {
{
std::lock_guard<std::mutex> Lock(Mutex);
@@ -123,62 +111,15 @@ private:
void work(ThreadPoolStrategy S, unsigned ThreadID) {
threadIndex = ThreadID;
S.apply_thread_strategy(ThreadID);
- // Note on jobserver deadlock avoidance:
- // GNU Make grants each invoked process one implicit job slot. Our
- // JobserverClient models this by returning an implicit JobSlot on the
- // first successful tryAcquire() in a process. This guarantees forward
- // progress without requiring a dedicated "always-on" thread here.
-
- static thread_local std::unique_ptr<ExponentialBackoff> Backoff;
-
while (true) {
- if (TheJobserver) {
- // Jobserver-mode scheduling:
- // - Acquire one job slot (with exponential backoff to avoid busy-wait).
- // - While holding the slot, drain and run tasks from the local queue.
- // - Release the slot when the queue is empty or when shutting down.
- // Rationale: Holding a slot amortizes acquire/release overhead over
- // multiple tasks and avoids requeue/yield churn, while still enforcing
- // the jobserver’s global concurrency limit. With K available slots,
- // up to K workers run tasks in parallel; within each worker tasks run
- // sequentially until the local queue is empty.
- ExponentialBackoff Backoff(std::chrono::hours(24));
- JobSlot Slot;
- do {
- if (Stop)
- return;
- Slot = TheJobserver->tryAcquire();
- if (Slot.isValid())
- break;
- } while (Backoff.waitForNextAttempt());
-
- auto SlotReleaser = llvm::make_scope_exit(
- [&] { TheJobserver->release(std::move(Slot)); });
-
- while (true) {
- std::function<void()> Task;
- {
- std::unique_lock<std::mutex> Lock(Mutex);
- Cond.wait(Lock, [&] { return Stop || !WorkStack.empty(); });
- if (Stop && WorkStack.empty())
- return;
- if (WorkStack.empty())
- break;
- Task = std::move(WorkStack.back());
- WorkStack.pop_back();
- }
- Task();
- }
- } else {
- std::unique_lock<std::mutex> Lock(Mutex);
- Cond.wait(Lock, [&] { return Stop || !WorkStack.empty(); });
- if (Stop)
- break;
- auto Task = std::move(WorkStack.back());
- WorkStack.pop_back();
- Lock.unlock();
- Task();
- }
+ std::unique_lock<std::mutex> Lock(Mutex);
+ Cond.wait(Lock, [&] { return Stop || !WorkStack.empty(); });
+ if (Stop)
+ break;
+ auto Task = std::move(WorkStack.back());
+ WorkStack.pop_back();
+ Lock.unlock();
+ Task();
}
}
@@ -189,20 +130,9 @@ private:
std::promise<void> ThreadsCreated;
std::vector<std::thread> Threads;
unsigned ThreadCount;
-
- JobserverClient *TheJobserver = nullptr;
};
-// A global raw pointer to the executor. Lifetime is managed by the
-// objects created within createExecutor().
-static Executor *TheExec = nullptr;
-static std::once_flag Flag;
-
-// This function will be called exactly once to create the executor.
-// It contains the necessary platform-specific logic. Since functions
-// called by std::call_once cannot return value, we have to set the
-// executor as a global variable.
-void createExecutor() {
+Executor *Executor::getDefaultExecutor() {
#ifdef _WIN32
// The ManagedStatic enables the ThreadPoolExecutor to be stopped via
// llvm_shutdown() which allows a "clean" fast exit, e.g. via _exit(). This
@@ -226,22 +156,16 @@ void createExecutor() {
ThreadPoolExecutor::Deleter>
ManagedExec;
static std::unique_ptr<ThreadPoolExecutor> Exec(&(*ManagedExec));
- TheExec = Exec.get();
+ return Exec.get();
#else
// ManagedStatic is not desired on other platforms. When `Exec` is destroyed
// by llvm_shutdown(), worker threads will clean up and invoke TLS
// destructors. This can lead to race conditions if other threads attempt to
// access TLS objects that have already been destroyed.
static ThreadPoolExecutor Exec(strategy);
- TheExec = &Exec;
+ return &Exec;
#endif
}
-
-Executor *Executor::getDefaultExecutor() {
- // Use std::call_once to lazily and safely initialize the executor.
- std::call_once(Flag, createExecutor);
- return TheExec;
-}
} // namespace
} // namespace detail