diff --git a/Cargo.lock b/Cargo.lock index 3447cc554737..765acaaae871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4468,6 +4468,7 @@ dependencies = [ "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "nsstring 0.1.0", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index e75a8cbe6820..baa72a28ad6c 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -31,6 +31,9 @@ dwrote = "0.9" dirs = "1.0" winapi = "0.3" +[target.'cfg(target_os = "linux")'.dependencies] +libc = "0.2" + [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.6" core-graphics = "0.17.1" diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 9c4417be831a..ca4913951379 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -42,7 +42,12 @@ use rayon; use num_cpus; use euclid::SideOffsets2D; use nsstring::nsAString; -//linux only//use thread_priority::*; + +#[cfg(target_os = "linux")] +use libc::{ + pthread_self, pthread_setschedparam, sched_param, + cpu_set_t, CPU_SET, pthread_setaffinity_np +}; #[cfg(target_os = "macos")] use core_foundation::string::CFString; @@ -1066,25 +1071,47 @@ pub unsafe extern "C" fn wr_thread_pool_new(low_priority: bool) -> *mut WrThread let priority_tag = if low_priority { "LP" } else { "" }; + // helper function to make sure that low priority threads really are low priority. + // it also sets the affinity so that WRWorkerX and WRWorkerLPX are both locked to + // the same core X, so one or the other can run, but not both: the total number + // of worker threads that's running should respect num_threads above, even if + // they exist in two separate pools. + #[cfg(target_os = "windows")] + fn set_thread_priority_and_affinity(low_priority:bool, thread_index: usize) { + unsafe { + SetThreadPriority( + GetCurrentThread(), + if low_priority { + -1 /* THREAD_PRIORITY_BELOW_NORMAL */ + } else { + 0 /* THREAD_PRIORITY_NORMAL */ + }); + SetThreadAffinityMask(GetCurrentThread(), 1usize << thread_index); + } + } + #[cfg(target_os = "linux")] + fn set_thread_priority_and_affinity(low_priority:bool, thread_index: usize) { + unsafe { + let thread_id = pthread_self(); + if low_priority { + let params = sched_param { + sched_priority: 0 + }; + pthread_setschedparam(thread_id, 3 /* SCHED_BATCH */, ¶ms); + } + let mut cpu_set = mem::zeroed::(); + CPU_SET(thread_index, &mut cpu_set); + pthread_setaffinity_np(thread_id, mem::size_of::(), &cpu_set); + } + } + #[cfg(not(any(target_os = "windows", target_os = "linux" )))] + fn set_thread_priority_and_affinity(_low_priority:bool, _thread_index: usize) { } + let worker = rayon::ThreadPoolBuilder::new() .thread_name(move |idx|{ format!("WRWorker{}#{}", priority_tag, idx) }) .num_threads(num_threads) .start_handler(move |idx| { - #[cfg(target_os = "windows")] - { - SetThreadPriority( - GetCurrentThread(), - if low_priority { - -1 /* THREAD_PRIORITY_BELOW_NORMAL */ - } else { - 0 /* THREAD_PRIORITY_NORMAL */ - }); - SetThreadAffinityMask(GetCurrentThread(), 1usize << idx); - } - /*let thread_id = thread_native_id(); - set_thread_priority(thread_id, - if low_priority { ThreadPriority::Min } else { ThreadPriority::Max }, - ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Normal));*/ + set_thread_priority_and_affinity(low_priority, idx); wr_register_thread_local_arena(); let name = format!("WRWorker{}#{}",priority_tag, idx); register_thread_with_profiler(name.clone()); diff --git a/gfx/webrender_bindings/src/lib.rs b/gfx/webrender_bindings/src/lib.rs index 933c00076d85..46e60a3e3e94 100644 --- a/gfx/webrender_bindings/src/lib.rs +++ b/gfx/webrender_bindings/src/lib.rs @@ -23,7 +23,8 @@ extern crate log; extern crate dwrote; #[cfg(target_os = "windows")] extern crate winapi; - +#[cfg(target_os = "linux")] +extern crate libc; #[cfg(target_os = "macos")] extern crate core_foundation;