From 34ac18d20c13a78914d447fee83204811a27b1e4 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 25 Oct 2021 00:19:45 +0200 Subject: Move runner into separate crate --- crates/runner/src/jobserver.rs | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 crates/runner/src/jobserver.rs (limited to 'crates/runner/src/jobserver.rs') diff --git a/crates/runner/src/jobserver.rs b/crates/runner/src/jobserver.rs new file mode 100644 index 0000000..3b6c856 --- /dev/null +++ b/crates/runner/src/jobserver.rs @@ -0,0 +1,77 @@ +use std::{os::unix::prelude::RawFd, slice}; + +use nix::{errno::Errno, fcntl::OFlag, poll, unistd}; + +use common::error::*; + +use super::util::unix; + +#[derive(Debug)] +pub struct Jobserver { + tokens: usize, + r: RawFd, + w: RawFd, +} + +impl Jobserver { + pub fn new(tokens: usize) -> Result { + let (r, w) = unistd::pipe2(OFlag::O_CLOEXEC | OFlag::O_NONBLOCK).context("pipe()")?; + + for _ in 0..tokens { + if let Err(_) = unistd::write(w, b"+") { + break; + } + } + unix::set_blocking(w, true)?; + + Ok(Jobserver { tokens, r, w }) + } + + pub fn wait(&mut self) -> u8 { + loop { + poll::poll( + &mut [poll::PollFd::new(self.r, poll::PollFlags::POLLIN)], + -1, + ) + .expect("poll()"); + + let mut token = 0; + match unistd::read(self.r, slice::from_mut(&mut token)) { + Ok(n) => { + assert!(n == 1); + return token; + } + Err(Errno::EAGAIN) => { + // Token was sniped by another task + continue; + } + error @ Err(_) => { + error.expect("read()"); + } + } + } + } + + pub fn post(&mut self, token: u8) { + let n = unistd::write(self.w, slice::from_ref(&token)).expect("write()"); + assert!(n == 1); + } + + pub fn set_cloexec(&mut self, cloexec: bool) -> Result<()> { + unix::set_cloexec(self.r, cloexec)?; + unix::set_cloexec(self.w, cloexec)?; + Ok(()) + } + + pub fn to_makeflags(&self) -> String { + format!(" -j{} --jobserver-auth={},{}", self.tokens, self.r, self.w) + } +} + +impl Drop for Jobserver { + fn drop(&mut self) { + // FIXME Logging + let _ = unistd::close(self.r); + let _ = unistd::close(self.w); + } +} -- cgit v1.2.3