mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #18566 - bholley:thread_state_fixes, r=Manishearth
Thread state fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1400435
This commit is contained in:
commit
c6381c66a0
3 changed files with 49 additions and 74 deletions
|
@ -461,7 +461,8 @@ impl LayoutThread {
|
||||||
ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)));
|
ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)));
|
||||||
|
|
||||||
let configuration =
|
let configuration =
|
||||||
rayon::Configuration::new().num_threads(layout_threads);
|
rayon::Configuration::new().num_threads(layout_threads)
|
||||||
|
.start_handler(|_| thread_state::initialize_layout_worker_thread());
|
||||||
let parallel_traversal = if layout_threads > 1 {
|
let parallel_traversal = if layout_threads > 1 {
|
||||||
Some(rayon::ThreadPool::new(configuration).expect("ThreadPool creation failed"))
|
Some(rayon::ThreadPool::new(configuration).expect("ThreadPool creation failed"))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use shared_lock::SharedRwLock;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use thread_state;
|
||||||
|
|
||||||
/// Global style data
|
/// Global style data
|
||||||
pub struct GlobalStyleData {
|
pub struct GlobalStyleData {
|
||||||
|
@ -39,6 +40,7 @@ fn thread_name(index: usize) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thread_startup(index: usize) {
|
fn thread_startup(index: usize) {
|
||||||
|
thread_state::initialize_layout_worker_thread();
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetJemallocThreadLocalArena(true);
|
Gecko_SetJemallocThreadLocalArena(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,12 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Supports dynamic assertions in debug builds about what sort of thread is
|
//! Supports dynamic assertions in about what sort of thread is running and
|
||||||
//! running and what state it's in.
|
//! what state it's in.
|
||||||
//!
|
|
||||||
//! In release builds, `get` returns 0. All of the other functions inline
|
|
||||||
//! away to nothing.
|
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
pub use self::imp::{enter, exit, get, initialize};
|
use std::cell::RefCell;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// A thread state flag, used for multiple assertions.
|
/// A thread state flag, used for multiple assertions.
|
||||||
|
@ -37,22 +34,12 @@ macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn $fun(self) -> bool {
|
pub fn $fun(self) -> bool {
|
||||||
self.contains($flag)
|
self.contains($flag)
|
||||||
}
|
}
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub fn $fun(self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
static TYPES: &'static [ThreadState] =
|
|
||||||
&[ $( $flag ),* ];
|
|
||||||
));
|
));
|
||||||
|
|
||||||
thread_types! {
|
thread_types! {
|
||||||
|
@ -60,64 +47,49 @@ thread_types! {
|
||||||
is_layout = LAYOUT;
|
is_layout = LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
|
||||||
mod imp {
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use super::{TYPES, ThreadState};
|
|
||||||
|
|
||||||
thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));
|
/// Initializes the current thread state.
|
||||||
|
pub fn initialize(x: ThreadState) {
|
||||||
/// Initialize the current thread state.
|
STATE.with(|ref k| {
|
||||||
pub fn initialize(x: ThreadState) {
|
if let Some(ref s) = *k.borrow() {
|
||||||
STATE.with(|ref k| {
|
panic!("Thread state already initialized as {:?}", s);
|
||||||
if let Some(ref s) = *k.borrow() {
|
}
|
||||||
panic!("Thread state already initialized as {:?}", s);
|
*k.borrow_mut() = Some(x);
|
||||||
}
|
});
|
||||||
*k.borrow_mut() = Some(x);
|
|
||||||
});
|
|
||||||
get(); // check the assertion below
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the current thread state.
|
|
||||||
pub fn get() -> ThreadState {
|
|
||||||
let state = STATE.with(|ref k| {
|
|
||||||
match *k.borrow() {
|
|
||||||
// This is one of the layout threads, that use rayon.
|
|
||||||
None => super::LAYOUT | super::IN_WORKER,
|
|
||||||
Some(s) => s,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Exactly one of the thread type flags should be set.
|
|
||||||
assert_eq!(1, TYPES.iter().filter(|&&ty| state.contains(ty)).count());
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enter into a given temporary state. Panics if re-entring.
|
|
||||||
pub fn enter(x: ThreadState) {
|
|
||||||
let state = get();
|
|
||||||
assert!(!state.intersects(x));
|
|
||||||
STATE.with(|ref k| {
|
|
||||||
*k.borrow_mut() = Some(state | x);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exit a given temporary state.
|
|
||||||
pub fn exit(x: ThreadState) {
|
|
||||||
let state = get();
|
|
||||||
assert!(state.contains(x));
|
|
||||||
STATE.with(|ref k| {
|
|
||||||
*k.borrow_mut() = Some(state & !x);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
/// Initializes the current thread as a layout worker thread.
|
||||||
#[allow(missing_docs)]
|
pub fn initialize_layout_worker_thread() {
|
||||||
mod imp {
|
initialize(LAYOUT | IN_WORKER);
|
||||||
use super::ThreadState;
|
}
|
||||||
#[inline(always)] pub fn initialize(_: ThreadState) { }
|
|
||||||
#[inline(always)] pub fn get() -> ThreadState { ThreadState::empty() }
|
/// Gets the current thread state.
|
||||||
#[inline(always)] pub fn enter(_: ThreadState) { }
|
pub fn get() -> ThreadState {
|
||||||
#[inline(always)] pub fn exit(_: ThreadState) { }
|
let state = STATE.with(|ref k| {
|
||||||
|
match *k.borrow() {
|
||||||
|
None => ThreadState::empty(), // Unknown thread.
|
||||||
|
Some(s) => s,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enters into a given temporary state. Panics if re-entring.
|
||||||
|
pub fn enter(x: ThreadState) {
|
||||||
|
let state = get();
|
||||||
|
debug_assert!(!state.intersects(x));
|
||||||
|
STATE.with(|ref k| {
|
||||||
|
*k.borrow_mut() = Some(state | x);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Exits a given temporary state.
|
||||||
|
pub fn exit(x: ThreadState) {
|
||||||
|
let state = get();
|
||||||
|
debug_assert!(state.contains(x));
|
||||||
|
STATE.with(|ref k| {
|
||||||
|
*k.borrow_mut() = Some(state & !x);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue