-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LLVM] Add GNU make jobserver support #145131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
//===- llvm/Support/Jobserver.h - Jobserver Client --------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file defines a client for the GNU Make jobserver protocol. This allows | ||
// LLVM tools to coordinate parallel execution with a parent `make` process. | ||
// | ||
// The jobserver protocol is a mechanism for GNU Make to share its pool of | ||
// available "job slots" with the subprocesses it invokes. This is particularly | ||
// useful for tools that can perform parallel operations themselves (e.g., a | ||
// multi-threaded linker or compiler). By participating in this protocol, a | ||
// tool can ensure the total number of concurrent jobs does not exceed the | ||
// limit specified by the user (e.g., `make -j8`). | ||
// | ||
// How it works: | ||
// | ||
// 1. Establishment: | ||
// A child process discovers the jobserver by inspecting the `MAKEFLAGS` | ||
// environment variable. If a jobserver is active, this variable will | ||
// contain a `--jobserver-auth=<value>` argument. The format of `<value>` | ||
// determines how to communicate with the server. | ||
// | ||
// 2. The Implicit Slot: | ||
// Every command invoked by `make` is granted one "implicit" job slot. This | ||
// means a tool can always perform at least one unit of work without needing | ||
// to communicate with the jobserver. This implicit slot should NEVER be | ||
// released back to the jobserver. | ||
// | ||
// 3. Acquiring and Releasing Slots: | ||
// On POSIX systems, the jobserver is implemented as a pipe. The | ||
// `--jobserver-auth` value specifies either a path to a named pipe | ||
// (`fifo:PATH`) or a pair of file descriptors (`R,W`). The pipe is | ||
// pre-loaded with single-character tokens, one for each available job slot. | ||
// | ||
// - To acquire an additional slot, a client reads a single-character token | ||
// from the pipe. | ||
// - To release a slot, the client must write the *exact same* character | ||
// token back to the pipe. | ||
// | ||
// It is critical that a client releases all acquired slots before it exits, | ||
// even in cases of error, to avoid deadlocking the build. | ||
// | ||
// Example: | ||
// A multi-threaded linker invoked by `make -j8` wants to use multiple | ||
// threads. It first checks for the jobserver. It knows it has one implicit | ||
// slot, so it can use one thread. It then tries to acquire 7 more slots by | ||
// reading 7 tokens from the jobserver pipe. If it only receives 3 tokens, | ||
// it knows it can use a total of 1 (implicit) + 3 (acquired) = 4 threads. | ||
// Before exiting, it must write the 3 tokens it read back to the pipe. | ||
// | ||
// For more context, see: | ||
// - GNU Make manual on job slots: | ||
// https://www.gnu.org/software/make/manual/html_node/Job-Slots.html | ||
// - LLVM RFC discussion on jobserver support: | ||
// https://discourse.llvm.org/t/rfc-adding-gnu-make-jobserver- | ||
// support-to-llvm-for-coordinated-parallelism/87034 | ||
// - Ninja’s jobserver support PR: | ||
// https://github.com/ninja-build/ninja/pull/2506 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_SUPPORT_JOBSERVER_H | ||
#define LLVM_SUPPORT_JOBSERVER_H | ||
|
||
#include "llvm/ADT/StringRef.h" | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace llvm { | ||
|
||
/// A JobSlot represents a single job slot that can be acquired from or released | ||
/// to a jobserver pool. This class is move-only. | ||
class JobSlot { | ||
public: | ||
/// Default constructor creates an invalid instance. | ||
JobSlot() = default; | ||
|
||
// Move operations are allowed. | ||
JobSlot(JobSlot &&Other) noexcept : Value(Other.Value) { | ||
Other.Value = kInvalidValue; | ||
} | ||
JobSlot &operator=(JobSlot &&Other) noexcept { | ||
if (this != &Other) { | ||
this->Value = Other.Value; | ||
Other.Value = kInvalidValue; | ||
} | ||
return *this; | ||
} | ||
|
||
// Copy operations are disallowed. | ||
JobSlot(const JobSlot &) = delete; | ||
JobSlot &operator=(const JobSlot &) = delete; | ||
|
||
/// Returns true if this instance is valid (either implicit or explicit). | ||
bool isValid() const { return Value >= 0; } | ||
|
||
/// Returns true if this instance represents the implicit job slot. | ||
bool isImplicit() const { return Value == kImplicitValue; } | ||
|
||
static JobSlot createExplicit(uint8_t V) { | ||
return JobSlot(static_cast<int16_t>(V)); | ||
} | ||
|
||
static JobSlot createImplicit() { return JobSlot(kImplicitValue); } | ||
|
||
uint8_t getExplicitValue() const; | ||
bool isExplicit() const { return isValid() && !isImplicit(); } | ||
|
||
private: | ||
friend class JobserverClient; | ||
friend class JobserverClientImpl; | ||
|
||
JobSlot(int16_t V) : Value(V) {} | ||
|
||
/// The jobserver pipe carries explicit tokens (bytes 0–255). We reserve two | ||
/// sentinels in Value for special cases: | ||
/// kInvalidValue (-1): no slot held | ||
/// kImplicitValue (INT16_MAX): implicit slot granted at startup (no pipe | ||
/// I/O) | ||
/// | ||
/// We use int16_t so Value can store 0–255 explicit tokens and | ||
/// sentinels without overflow, enforces fixed 16-bit width, and avoids | ||
/// unsigned/signed mix-ups. | ||
static constexpr int16_t kInvalidValue = -1; | ||
static constexpr int16_t kImplicitValue = INT16_MAX; | ||
int16_t Value = kInvalidValue; | ||
}; | ||
|
||
/// The public interface for a jobserver client. | ||
/// This client is a lazy-initialized singleton that is created on first use. | ||
class JobserverClient { | ||
public: | ||
virtual ~JobserverClient(); | ||
|
||
/// Tries to acquire a job slot from the pool. On failure (e.g., if the pool | ||
/// is empty), this returns an invalid JobSlot instance. The first successful | ||
/// call will always return the implicit slot. | ||
virtual JobSlot tryAcquire() = 0; | ||
|
||
/// Releases a job slot back to the pool. | ||
virtual void release(JobSlot Slot) = 0; | ||
|
||
/// Returns the number of job slots available, as determined on first use. | ||
/// This value is cached. Returns 0 if no jobserver is active. | ||
virtual unsigned getNumJobs() const = 0; | ||
|
||
/// Returns the singleton instance of the JobserverClient. | ||
/// The instance is created on the first call to this function. | ||
/// Returns a nullptr if no jobserver is configured or an error occurs. | ||
static JobserverClient *getInstance(); | ||
|
||
/// Resets the singleton instance. For testing purposes only. | ||
static void resetForTesting(); | ||
}; | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_SUPPORT_JOBSERVER_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.