std: More TLS micro-optimization

This commit is contained in:
Brian Anderson 2013-08-17 01:24:29 -07:00
parent 468d023fe9
commit 5402786f94
2 changed files with 31 additions and 12 deletions

View File

@ -26,7 +26,9 @@ pub trait Local {
} }
impl Local for Task { impl Local for Task {
#[inline]
fn put(value: ~Task) { unsafe { local_ptr::put(value) } } fn put(value: ~Task) { unsafe { local_ptr::put(value) } }
#[inline]
fn take() -> ~Task { unsafe { local_ptr::take() } } fn take() -> ~Task { unsafe { local_ptr::take() } }
fn exists() -> bool { local_ptr::exists() } fn exists() -> bool { local_ptr::exists() }
fn borrow<T>(f: &fn(&mut Task) -> T) -> T { fn borrow<T>(f: &fn(&mut Task) -> T) -> T {
@ -43,7 +45,9 @@ impl Local for Task {
None => { rtabort!("function failed in local_borrow") } None => { rtabort!("function failed in local_borrow") }
} }
} }
#[inline]
unsafe fn unsafe_borrow() -> *mut Task { local_ptr::unsafe_borrow() } unsafe fn unsafe_borrow() -> *mut Task { local_ptr::unsafe_borrow() }
#[inline]
unsafe fn try_unsafe_borrow() -> Option<*mut Task> { unsafe fn try_unsafe_borrow() -> Option<*mut Task> {
local_ptr::try_unsafe_borrow() local_ptr::try_unsafe_borrow()
} }
@ -57,12 +61,12 @@ impl Local for Scheduler {
task.sched = Some(value.take()); task.sched = Some(value.take());
}; };
} }
#[inline]
fn take() -> ~Scheduler { fn take() -> ~Scheduler {
do Local::borrow::<Task,~Scheduler> |task| { unsafe {
let sched = task.sched.take_unwrap(); // XXX: Unsafe for speed
let task = task; let task = Local::unsafe_borrow::<Task>();
task.sched = None; (*task).sched.take_unwrap()
sched
} }
} }
fn exists() -> bool { fn exists() -> bool {
@ -97,10 +101,17 @@ impl Local for Scheduler {
} }
} }
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> {
if Local::exists::<Scheduler>() { match Local::try_unsafe_borrow::<Task>() {
Some(Local::unsafe_borrow()) Some(task) => {
} else { match (*task).sched {
None Some(~ref mut sched) => {
let s: *mut Scheduler = &mut *sched;
Some(s)
}
None => None
}
}
None => None
} }
} }
} }

View File

@ -40,6 +40,7 @@ pub fn init_tls_key() {
/// # Safety note /// # Safety note
/// ///
/// Does not validate the pointer type. /// Does not validate the pointer type.
#[inline]
pub unsafe fn put<T>(sched: ~T) { pub unsafe fn put<T>(sched: ~T) {
let key = tls_key(); let key = tls_key();
let void_ptr: *mut c_void = cast::transmute(sched); let void_ptr: *mut c_void = cast::transmute(sched);
@ -51,6 +52,7 @@ pub unsafe fn put<T>(sched: ~T) {
/// # Safety note /// # Safety note
/// ///
/// Does not validate the pointer type. /// Does not validate the pointer type.
#[inline]
pub unsafe fn take<T>() -> ~T { pub unsafe fn take<T>() -> ~T {
let key = tls_key(); let key = tls_key();
let void_ptr: *mut c_void = tls::get(key); let void_ptr: *mut c_void = tls::get(key);
@ -99,10 +101,15 @@ pub unsafe fn borrow<T>(f: &fn(&mut T)) {
/// Because this leaves the value in thread-local storage it is possible /// Because this leaves the value in thread-local storage it is possible
/// For the Scheduler pointer to be aliased /// For the Scheduler pointer to be aliased
pub unsafe fn unsafe_borrow<T>() -> *mut T { pub unsafe fn unsafe_borrow<T>() -> *mut T {
match try_unsafe_borrow() { let key = tls_key();
Some(p) => p, let mut void_ptr: *mut c_void = tls::get(key);
None => rtabort!("thread-local pointer is null. bogus!") if void_ptr.is_null() {
rtabort!("thread-local pointer is null. bogus!");
} }
let ptr: *mut *mut c_void = &mut void_ptr;
let ptr: *mut ~T = ptr as *mut ~T;
let ptr: *mut T = &mut **ptr;
return ptr;
} }
pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> { pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
@ -119,6 +126,7 @@ pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
} }
} }
#[inline]
fn tls_key() -> tls::Key { fn tls_key() -> tls::Key {
match maybe_tls_key() { match maybe_tls_key() {
Some(key) => key, Some(key) => key,