brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · 79028ee Raw
80 lines · plain
1//==- llvm/Support/Windows/Jobserver.inc - Windows Jobserver Impl -*- C++ -*-=//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Windows-specific parts of the JobserverClient class.10// On Windows, the jobserver is implemented using a named semaphore.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Support/Windows/WindowsSupport.h"15#include <atomic>16#include <cassert>17 18namespace llvm {19/// The constructor for the Windows jobserver client. It attempts to open a20/// handle to an existing named semaphore, the name of which is provided by21/// GNU make in the --jobserver-auth argument. If the semaphore is opened22/// successfully, the client is marked as initialized.23JobserverClientImpl::JobserverClientImpl(const JobserverConfig &Config) {24  Semaphore = (void *)::OpenSemaphoreA(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE,25                                       FALSE, Config.Path.c_str());26  if (Semaphore != nullptr)27    IsInitialized = true;28}29 30/// The destructor closes the handle to the semaphore, releasing the resource.31JobserverClientImpl::~JobserverClientImpl() {32  if (Semaphore != nullptr)33    ::CloseHandle((HANDLE)Semaphore);34}35 36/// Tries to acquire a job slot. The first call always returns the implicit37/// slot. Subsequent calls use a non-blocking wait on the semaphore38/// (`WaitForSingleObject` with a timeout of 0). If the wait succeeds, the39/// semaphore's count is decremented, and an explicit job slot is acquired.40/// If the wait times out, it means no slots are available, and an invalid41/// slot is returned.42JobSlot JobserverClientImpl::tryAcquire() {43  if (!IsInitialized)44    return JobSlot();45 46  // First, grant the implicit slot.47  if (HasImplicitSlot.exchange(false, std::memory_order_acquire)) {48    return JobSlot::createImplicit();49  }50 51  // Try to acquire a slot from the semaphore without blocking.52  if (::WaitForSingleObject((HANDLE)Semaphore, 0) == WAIT_OBJECT_0) {53    // The explicit token value is arbitrary on Windows, as the semaphore54    // count is the real resource.55    return JobSlot::createExplicit(1);56  }57 58  return JobSlot(); // Invalid slot59}60 61/// Releases a job slot back to the pool. If the slot is implicit, it simply62/// resets a flag. For an explicit slot, it increments the semaphore's count63/// by one using `ReleaseSemaphore`, making the slot available to other64/// processes.65void JobserverClientImpl::release(JobSlot Slot) {66  if (!IsInitialized || !Slot.isValid())67    return;68 69  if (Slot.isImplicit()) {70    [[maybe_unused]] bool was_already_released =71        HasImplicitSlot.exchange(true, std::memory_order_release);72    assert(!was_already_released && "Implicit slot released twice");73    return;74  }75 76  // Release the slot by incrementing the semaphore count.77  (void)::ReleaseSemaphore((HANDLE)Semaphore, 1, NULL);78}79} // namespace llvm80