From 8fc1d9db21fa9d4abd9b40d09be8fa061abb3bb5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 17 Aug 2013 02:12:08 -0700 Subject: [PATCH] std: Convert the runtime TLS key to a Rust global to avoid FFI --- src/libstd/rt/local_ptr.rs | 34 ++++++++++++++++++---------------- src/rt/rust_builtin.cpp | 17 ++++++----------- src/rt/rustrt.def.in | 1 - 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index 3125a1da937..e843fd1adef 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -23,14 +23,16 @@ use option::{Option, Some, None}; use unstable::finally::Finally; use tls = rt::thread_local_storage; +static mut RT_TLS_KEY: tls::Key = -1; + /// Initialize the TLS key. Other ops will fail if this isn't executed first. #[fixed_stack_segment] #[inline(never)] pub fn init_tls_key() { unsafe { - rust_initialize_rt_tls_key(); + rust_initialize_rt_tls_key(&mut RT_TLS_KEY); extern { - fn rust_initialize_rt_tls_key(); + fn rust_initialize_rt_tls_key(key: *mut tls::Key); } } } @@ -151,15 +153,10 @@ fn tls_key() -> tls::Key { } } -#[fixed_stack_segment] -#[inline(never)] -fn maybe_tls_key() -> Option { +#[inline] +#[cfg(not(test))] +pub fn maybe_tls_key() -> Option { unsafe { - let key: *mut c_void = rust_get_rt_tls_key(); - let key: &mut tls::Key = cast::transmute(key); - let key = *key; - // Check that the key has been initialized. - // NB: This is a little racy because, while the key is // initalized under a mutex and it's assumed to be initalized // in the Scheduler ctor by any thread that needs to use it, @@ -170,14 +167,19 @@ fn maybe_tls_key() -> Option { // another thread. I think this is fine since the only action // they could take if it was initialized would be to check the // thread-local value and see that it's not set. - if key != -1 { - return Some(key); + if RT_TLS_KEY != -1 { + return Some(RT_TLS_KEY); } else { return None; } } - - extern { - fn rust_get_rt_tls_key() -> *mut c_void; - } +} + +// XXX: The boundary between the running runtime and the testing runtime +// seems to be fuzzy at the moment, and trying to use two different keys +// results in disaster. This should not be necessary. +#[inline] +#[cfg(test)] +pub fn maybe_tls_key() -> Option { + unsafe { ::cast::transmute(::realstd::rt::local_ptr::maybe_tls_key()) } } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 6f3a3bd3686..27cc486c39e 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -447,19 +447,14 @@ rust_readdir() { #endif #ifndef _WIN32 -pthread_key_t rt_key = -1; +typedef pthread_key_t tls_key; #else -DWORD rt_key = -1; +typedef DWORD tls_key; #endif -extern "C" void* -rust_get_rt_tls_key() { - return &rt_key; -} - // Initialize the TLS key used by the new scheduler extern "C" CDECL void -rust_initialize_rt_tls_key() { +rust_initialize_rt_tls_key(tls_key *key) { static lock_and_signal init_lock; static bool initialized = false; @@ -469,10 +464,10 @@ rust_initialize_rt_tls_key() { if (!initialized) { #ifndef _WIN32 - assert(!pthread_key_create(&rt_key, NULL)); + assert(!pthread_key_create(key, NULL)); #else - rt_key = TlsAlloc(); - assert(rt_key != TLS_OUT_OF_INDEXES); + *key = TlsAlloc(); + assert(*key != TLS_OUT_OF_INDEXES); #endif initialized = true; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 6e95d96012b..b668d394406 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -143,7 +143,6 @@ linenoiseHistoryLoad rust_raw_thread_start rust_raw_thread_join rust_raw_thread_delete -rust_get_rt_tls_key swap_registers rust_readdir rust_opendir