Skip to content

Commit d987b46

Browse files
committed
Auto merge of #56946 - Zoxc:jobserver, r=nikomatsakis
Add support for using a jobserver with Rayon The Rayon changes are here: Zoxc/rayon#2 cc @alexcrichton r? @nikomatsakis
2 parents f3730f9 + 5c78fa8 commit d987b46

File tree

9 files changed

+192
-46
lines changed

9 files changed

+192
-46
lines changed

Cargo.lock

+16-14
Original file line numberDiff line numberDiff line change
@@ -2358,8 +2358,8 @@ dependencies = [
23582358
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
23592359
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
23602360
"polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
2361-
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2362-
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2361+
"rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
2362+
"rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
23632363
"rustc_apfloat 0.0.0",
23642364
"rustc_data_structures 0.0.0",
23652365
"rustc_errors 0.0.0",
@@ -2409,8 +2409,8 @@ dependencies = [
24092409
"rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
24102410
"rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
24112411
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
2412-
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2413-
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2412+
"rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
2413+
"rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
24142414
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
24152415
"stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
24162416
]
@@ -2508,23 +2508,23 @@ dependencies = [
25082508

25092509
[[package]]
25102510
name = "rustc-rayon"
2511-
version = "0.1.1"
2511+
version = "0.1.2"
25122512
source = "registry+https://github.com/rust-lang/crates.io-index"
25132513
dependencies = [
2514+
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
25142515
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
2515-
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2516+
"rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
25162517
]
25172518

25182519
[[package]]
25192520
name = "rustc-rayon-core"
2520-
version = "0.1.1"
2521+
version = "0.1.2"
25212522
source = "registry+https://github.com/rust-lang/crates.io-index"
25222523
dependencies = [
25232524
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
25242525
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
25252526
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
25262527
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
2527-
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
25282528
]
25292529

25302530
[[package]]
@@ -2672,11 +2672,13 @@ dependencies = [
26722672
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
26732673
"ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
26742674
"graphviz 0.0.0",
2675+
"jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
2676+
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
26752677
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
26762678
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
26772679
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
2678-
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2679-
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2680+
"rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
2681+
"rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
26802682
"rustc_cratesio_shim 0.0.0",
26812683
"serialize 0.0.0",
26822684
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2692,7 +2694,7 @@ dependencies = [
26922694
"graphviz 0.0.0",
26932695
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
26942696
"rustc 0.0.0",
2695-
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2697+
"rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
26962698
"rustc_allocator 0.0.0",
26972699
"rustc_borrowck 0.0.0",
26982700
"rustc_codegen_utils 0.0.0",
@@ -2758,7 +2760,7 @@ version = "0.0.0"
27582760
dependencies = [
27592761
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
27602762
"rustc 0.0.0",
2761-
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
2763+
"rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
27622764
"rustc_allocator 0.0.0",
27632765
"rustc_borrowck 0.0.0",
27642766
"rustc_codegen_utils 0.0.0",
@@ -4190,8 +4192,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
41904192
"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952"
41914193
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
41924194
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
4193-
"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
4194-
"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
4195+
"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
4196+
"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
41954197
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
41964198
"checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
41974199
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"

src/librustc/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ num_cpus = "1.0"
2020
scoped-tls = "1.0"
2121
log = { version = "0.4", features = ["release_max_level_info", "std"] }
2222
polonius-engine = "0.6.2"
23-
rustc-rayon = "0.1.1"
24-
rustc-rayon-core = "0.1.1"
23+
rustc-rayon = "0.1.2"
24+
rustc-rayon-core = "0.1.2"
2525
rustc_apfloat = { path = "../librustc_apfloat" }
2626
rustc_target = { path = "../librustc_target" }
2727
rustc_data_structures = { path = "../librustc_data_structures" }

src/librustc/session/mod.rs

+3-27
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ use crate::util::profiling::SelfProfiler;
3434

3535
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
3636
use rustc_data_structures::flock;
37-
use jobserver::Client;
37+
use rustc_data_structures::jobserver;
38+
use ::jobserver::Client;
3839

3940
use std;
4041
use std::cell::{self, Cell, RefCell};
@@ -1230,32 +1231,7 @@ pub fn build_session_(
12301231
optimization_fuel,
12311232
print_fuel_crate,
12321233
print_fuel,
1233-
// Note that this is unsafe because it may misinterpret file descriptors
1234-
// on Unix as jobserver file descriptors. We hopefully execute this near
1235-
// the beginning of the process though to ensure we don't get false
1236-
// positives, or in other words we try to execute this before we open
1237-
// any file descriptors ourselves.
1238-
//
1239-
// Pick a "reasonable maximum" if we don't otherwise have
1240-
// a jobserver in our environment, capping out at 32 so we
1241-
// don't take everything down by hogging the process run queue.
1242-
// The fixed number is used to have deterministic compilation
1243-
// across machines.
1244-
//
1245-
// Also note that we stick this in a global because there could be
1246-
// multiple `Session` instances in this process, and the jobserver is
1247-
// per-process.
1248-
jobserver: unsafe {
1249-
static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _;
1250-
static INIT: std::sync::Once = std::sync::ONCE_INIT;
1251-
INIT.call_once(|| {
1252-
let client = Client::from_env().unwrap_or_else(|| {
1253-
Client::new(32).expect("failed to create jobserver")
1254-
});
1255-
GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));
1256-
});
1257-
(*GLOBAL_JOBSERVER).clone()
1258-
},
1234+
jobserver: jobserver::client(),
12591235
has_global_allocator: Once::new(),
12601236
has_panic_handler: Once::new(),
12611237
driver_lint_caps,

src/librustc/ty/query/job.rs

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{fmt, ptr};
77
use rustc_data_structures::fx::FxHashSet;
88
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
99
use rustc_data_structures::OnDrop;
10+
use rustc_data_structures::jobserver;
1011
use syntax_pos::Span;
1112

1213
use crate::ty::tls;
@@ -198,7 +199,11 @@ impl<'tcx> QueryLatch<'tcx> {
198199
// we have to be in the `wait` call. This is ensured by the deadlock handler
199200
// getting the self.info lock.
200201
rayon_core::mark_blocked();
202+
jobserver::release_thread();
201203
waiter.condvar.wait(&mut info);
204+
// Release the lock before we potentially block in `acquire_thread`
205+
mem::drop(info);
206+
jobserver::acquire_thread();
202207
}
203208
}
204209

src/librustc_data_structures/Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ crate-type = ["dylib"]
1212
[dependencies]
1313
ena = "0.11"
1414
log = "0.4"
15+
jobserver_crate = { version = "0.1", package = "jobserver" }
16+
lazy_static = "1"
1517
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
1618
serialize = { path = "../libserialize" }
1719
graphviz = { path = "../libgraphviz" }
1820
cfg-if = "0.1.2"
1921
stable_deref_trait = "1.0.0"
20-
rayon = { version = "0.1.1", package = "rustc-rayon" }
21-
rayon-core = { version = "0.1.1", package = "rustc-rayon-core" }
22+
rayon = { version = "0.1.2", package = "rustc-rayon" }
23+
rayon-core = { version = "0.1.2", package = "rustc-rayon-core" }
2224
rustc-hash = "1.0.1"
2325
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
2426

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use jobserver_crate::{Client, HelperThread, Acquired};
2+
use lazy_static::lazy_static;
3+
use std::sync::{Condvar, Arc, Mutex};
4+
use std::mem;
5+
6+
#[derive(Default)]
7+
struct LockedProxyData {
8+
/// The number of free thread tokens, this may include the implicit token given to the process
9+
free: usize,
10+
11+
/// The number of threads waiting for a token
12+
waiters: usize,
13+
14+
/// The number of tokens we requested from the server
15+
requested: usize,
16+
17+
/// Stored tokens which will be dropped when we no longer need them
18+
tokens: Vec<Acquired>,
19+
}
20+
21+
impl LockedProxyData {
22+
fn request_token(&mut self, thread: &Mutex<HelperThread>) {
23+
self.requested += 1;
24+
thread.lock().unwrap().request_token();
25+
}
26+
27+
fn release_token(&mut self, cond_var: &Condvar) {
28+
if self.waiters > 0 {
29+
self.free += 1;
30+
cond_var.notify_one();
31+
} else {
32+
if self.tokens.is_empty() {
33+
// We are returning the implicit token
34+
self.free += 1;
35+
} else {
36+
// Return a real token to the server
37+
self.tokens.pop().unwrap();
38+
}
39+
}
40+
}
41+
42+
fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
43+
if self.free > 0 {
44+
self.free -= 1;
45+
self.waiters -= 1;
46+
47+
// We stole some token reqested by someone else
48+
// Request another one
49+
if self.requested + self.free < self.waiters {
50+
self.request_token(thread);
51+
}
52+
53+
true
54+
} else {
55+
false
56+
}
57+
}
58+
59+
fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
60+
self.requested -= 1;
61+
62+
// Does anything need this token?
63+
if self.waiters > 0 {
64+
self.free += 1;
65+
self.tokens.push(token);
66+
cond_var.notify_one();
67+
} else {
68+
// Otherwise we'll just drop it
69+
mem::drop(token);
70+
}
71+
}
72+
}
73+
74+
#[derive(Default)]
75+
struct ProxyData {
76+
lock: Mutex<LockedProxyData>,
77+
cond_var: Condvar,
78+
}
79+
80+
/// A helper type which makes managing jobserver tokens easier.
81+
/// It also allows you to treat the implicit token given to the process
82+
/// in the same manner as requested tokens.
83+
struct Proxy {
84+
thread: Mutex<HelperThread>,
85+
data: Arc<ProxyData>,
86+
}
87+
88+
lazy_static! {
89+
// We can only call `from_env` once per process
90+
91+
// Note that this is unsafe because it may misinterpret file descriptors
92+
// on Unix as jobserver file descriptors. We hopefully execute this near
93+
// the beginning of the process though to ensure we don't get false
94+
// positives, or in other words we try to execute this before we open
95+
// any file descriptors ourselves.
96+
//
97+
// Pick a "reasonable maximum" if we don't otherwise have
98+
// a jobserver in our environment, capping out at 32 so we
99+
// don't take everything down by hogging the process run queue.
100+
// The fixed number is used to have deterministic compilation
101+
// across machines.
102+
//
103+
// Also note that we stick this in a global because there could be
104+
// multiple rustc instances in this process, and the jobserver is
105+
// per-process.
106+
static ref GLOBAL_CLIENT: Client = unsafe {
107+
Client::from_env().unwrap_or_else(|| {
108+
Client::new(32).expect("failed to create jobserver")
109+
})
110+
};
111+
112+
static ref GLOBAL_PROXY: Proxy = {
113+
let data = Arc::new(ProxyData::default());
114+
115+
Proxy {
116+
data: data.clone(),
117+
thread: Mutex::new(client().into_helper_thread(move |token| {
118+
data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
119+
}).unwrap()),
120+
}
121+
};
122+
}
123+
124+
pub fn client() -> Client {
125+
GLOBAL_CLIENT.clone()
126+
}
127+
128+
pub fn acquire_thread() {
129+
GLOBAL_PROXY.acquire_token();
130+
}
131+
132+
pub fn release_thread() {
133+
GLOBAL_PROXY.release_token();
134+
}
135+
136+
impl Proxy {
137+
fn release_token(&self) {
138+
self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
139+
}
140+
141+
fn acquire_token(&self) {
142+
let mut data = self.data.lock.lock().unwrap();
143+
data.waiters += 1;
144+
if data.take_token(&self.thread) {
145+
return;
146+
}
147+
// Request a token for us
148+
data.request_token(&self.thread);
149+
loop {
150+
data = self.data.cond_var.wait(data).unwrap();
151+
if data.take_token(&self.thread) {
152+
return;
153+
}
154+
}
155+
}
156+
}

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub mod fx;
7777
pub mod graph;
7878
pub mod indexed_vec;
7979
pub mod interner;
80+
pub mod jobserver;
8081
pub mod obligation_forest;
8182
pub mod owning_ref;
8283
pub mod ptr_key;

src/librustc_driver/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ arena = { path = "../libarena" }
1313
graphviz = { path = "../libgraphviz" }
1414
log = "0.4"
1515
env_logger = { version = "0.5", default-features = false }
16-
rustc-rayon = "0.1.1"
16+
rustc-rayon = "0.1.2"
1717
scoped-tls = "1.0"
1818
rustc = { path = "../librustc" }
1919
rustc_allocator = { path = "../librustc_allocator" }

src/librustc_driver/driver.rs

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use rustc_allocator as allocator;
1717
use rustc_borrowck as borrowck;
1818
use rustc_codegen_utils::codegen_backend::CodegenBackend;
1919
use rustc_data_structures::sync::{self, Lock};
20+
#[cfg(parallel_compiler)]
21+
use rustc_data_structures::jobserver;
2022
use rustc_incremental;
2123
use rustc_metadata::creader::CrateLoader;
2224
use rustc_metadata::cstore::{self, CStore};
@@ -72,6 +74,8 @@ pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::
7274
let gcx_ptr = &Lock::new(0);
7375

7476
let config = ThreadPoolBuilder::new()
77+
.acquire_thread_handler(jobserver::acquire_thread)
78+
.release_thread_handler(jobserver::release_thread)
7579
.num_threads(Session::threads_from_count(opts.debugging_opts.threads))
7680
.deadlock_handler(|| unsafe { ty::query::handle_deadlock() })
7781
.stack_size(::STACK_SIZE);

0 commit comments

Comments
 (0)