Skip to content
Permalink
Browse files

Clean up jobserver integration

  • Loading branch information...
Zoxc committed Apr 8, 2019
1 parent 3750348 commit 03727a4f257fc86b467457a1e87d06d56e62d5f0
Showing with 8 additions and 122 deletions.
  1. +1 −1 src/librustc_data_structures/Cargo.toml
  2. +7 −121 src/librustc_data_structures/jobserver.rs
@@ -12,7 +12,7 @@ crate-type = ["dylib"]
[dependencies]
ena = "0.13"
log = "0.4"
jobserver_crate = { version = "0.1", package = "jobserver" }
jobserver_crate = { version = "0.1.13", package = "jobserver" }
lazy_static = "1"
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
serialize = { path = "../libserialize" }
@@ -1,89 +1,5 @@
use jobserver_crate::{Client, HelperThread, Acquired};
use jobserver_crate::Client;
use lazy_static::lazy_static;
use std::sync::{Condvar, Arc, Mutex};
use std::mem;

#[derive(Default)]
struct LockedProxyData {
/// The number of free thread tokens, this may include the implicit token given to the process
free: usize,

/// The number of threads waiting for a token
waiters: usize,

/// The number of tokens we requested from the server
requested: usize,

/// Stored tokens which will be dropped when we no longer need them
tokens: Vec<Acquired>,
}

impl LockedProxyData {
fn request_token(&mut self, thread: &Mutex<HelperThread>) {
self.requested += 1;
thread.lock().unwrap().request_token();
}

fn release_token(&mut self, cond_var: &Condvar) {
if self.waiters > 0 {
self.free += 1;
cond_var.notify_one();
} else {
if self.tokens.is_empty() {
// We are returning the implicit token
self.free += 1;
} else {
// Return a real token to the server
self.tokens.pop().unwrap();
}
}
}

fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
if self.free > 0 {
self.free -= 1;
self.waiters -= 1;

// We stole some token reqested by someone else
// Request another one
if self.requested + self.free < self.waiters {
self.request_token(thread);
}

true
} else {
false
}
}

fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
self.requested -= 1;

// Does anything need this token?
if self.waiters > 0 {
self.free += 1;
self.tokens.push(token);
cond_var.notify_one();
} else {
// Otherwise we'll just drop it
mem::drop(token);
}
}
}

#[derive(Default)]
struct ProxyData {
lock: Mutex<LockedProxyData>,
cond_var: Condvar,
}

/// A helper type which makes managing jobserver tokens easier.
/// It also allows you to treat the implicit token given to the process
/// in the same manner as requested tokens.
struct Proxy {
thread: Mutex<HelperThread>,
data: Arc<ProxyData>,
}

lazy_static! {
// We can only call `from_env` once per process
@@ -105,52 +21,22 @@ lazy_static! {
// per-process.
static ref GLOBAL_CLIENT: Client = unsafe {
Client::from_env().unwrap_or_else(|| {
Client::new(32).expect("failed to create jobserver")
let client = Client::new(32).expect("failed to create jobserver");
// Acquire a token for the main thread which we can release later
client.acquire_raw().ok();
client
})
};

static ref GLOBAL_PROXY: Proxy = {
let data = Arc::new(ProxyData::default());

Proxy {
data: data.clone(),
thread: Mutex::new(client().into_helper_thread(move |token| {
data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
}).unwrap()),
}
};
}

pub fn client() -> Client {
GLOBAL_CLIENT.clone()
}

pub fn acquire_thread() {
GLOBAL_PROXY.acquire_token();
GLOBAL_CLIENT.acquire_raw().ok();
}

pub fn release_thread() {
GLOBAL_PROXY.release_token();
}

impl Proxy {
fn release_token(&self) {
self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
}

fn acquire_token(&self) {
let mut data = self.data.lock.lock().unwrap();
data.waiters += 1;
if data.take_token(&self.thread) {
return;
}
// Request a token for us
data.request_token(&self.thread);
loop {
data = self.data.cond_var.wait(data).unwrap();
if data.take_token(&self.thread) {
return;
}
}
}
GLOBAL_CLIENT.release_raw().ok();
}

0 comments on commit 03727a4

Please sign in to comment.
You can’t perform that action at this time.