std: Convert the runtime TLS key to a Rust global to avoid FFI

This commit is contained in:
Brian Anderson 2013-08-17 02:12:08 -07:00
parent a37bdde3f9
commit 8fc1d9db21
3 changed files with 24 additions and 28 deletions

View File

@ -23,14 +23,16 @@ use option::{Option, Some, None};
use unstable::finally::Finally; use unstable::finally::Finally;
use tls = rt::thread_local_storage; 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. /// Initialize the TLS key. Other ops will fail if this isn't executed first.
#[fixed_stack_segment] #[fixed_stack_segment]
#[inline(never)] #[inline(never)]
pub fn init_tls_key() { pub fn init_tls_key() {
unsafe { unsafe {
rust_initialize_rt_tls_key(); rust_initialize_rt_tls_key(&mut RT_TLS_KEY);
extern { 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]
#[inline(never)] #[cfg(not(test))]
fn maybe_tls_key() -> Option<tls::Key> { pub fn maybe_tls_key() -> Option<tls::Key> {
unsafe { 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 // NB: This is a little racy because, while the key is
// initalized under a mutex and it's assumed to be initalized // initalized under a mutex and it's assumed to be initalized
// in the Scheduler ctor by any thread that needs to use it, // in the Scheduler ctor by any thread that needs to use it,
@ -170,14 +167,19 @@ fn maybe_tls_key() -> Option<tls::Key> {
// another thread. I think this is fine since the only action // another thread. I think this is fine since the only action
// they could take if it was initialized would be to check the // they could take if it was initialized would be to check the
// thread-local value and see that it's not set. // thread-local value and see that it's not set.
if key != -1 { if RT_TLS_KEY != -1 {
return Some(key); return Some(RT_TLS_KEY);
} else { } else {
return None; 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<tls::Key> {
unsafe { ::cast::transmute(::realstd::rt::local_ptr::maybe_tls_key()) }
} }

View File

@ -447,19 +447,14 @@ rust_readdir() {
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
pthread_key_t rt_key = -1; typedef pthread_key_t tls_key;
#else #else
DWORD rt_key = -1; typedef DWORD tls_key;
#endif #endif
extern "C" void*
rust_get_rt_tls_key() {
return &rt_key;
}
// Initialize the TLS key used by the new scheduler // Initialize the TLS key used by the new scheduler
extern "C" CDECL void extern "C" CDECL void
rust_initialize_rt_tls_key() { rust_initialize_rt_tls_key(tls_key *key) {
static lock_and_signal init_lock; static lock_and_signal init_lock;
static bool initialized = false; static bool initialized = false;
@ -469,10 +464,10 @@ rust_initialize_rt_tls_key() {
if (!initialized) { if (!initialized) {
#ifndef _WIN32 #ifndef _WIN32
assert(!pthread_key_create(&rt_key, NULL)); assert(!pthread_key_create(key, NULL));
#else #else
rt_key = TlsAlloc(); *key = TlsAlloc();
assert(rt_key != TLS_OUT_OF_INDEXES); assert(*key != TLS_OUT_OF_INDEXES);
#endif #endif
initialized = true; initialized = true;

View File

@ -143,7 +143,6 @@ linenoiseHistoryLoad
rust_raw_thread_start rust_raw_thread_start
rust_raw_thread_join rust_raw_thread_join
rust_raw_thread_delete rust_raw_thread_delete
rust_get_rt_tls_key
swap_registers swap_registers
rust_readdir rust_readdir
rust_opendir rust_opendir