Skip to content

Commit 8fc1d9d

Browse files
committed
std: Convert the runtime TLS key to a Rust global to avoid FFI
1 parent a37bdde commit 8fc1d9d

File tree

3 files changed

+23
-27
lines changed

3 files changed

+23
-27
lines changed

src/libstd/rt/local_ptr.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ use option::{Option, Some, None};
2323
use unstable::finally::Finally;
2424
use tls = rt::thread_local_storage;
2525

26+
static mut RT_TLS_KEY: tls::Key = -1;
27+
2628
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
2729
#[fixed_stack_segment]
2830
#[inline(never)]
2931
pub fn init_tls_key() {
3032
unsafe {
31-
rust_initialize_rt_tls_key();
33+
rust_initialize_rt_tls_key(&mut RT_TLS_KEY);
3234
extern {
33-
fn rust_initialize_rt_tls_key();
35+
fn rust_initialize_rt_tls_key(key: *mut tls::Key);
3436
}
3537
}
3638
}
@@ -151,15 +153,10 @@ fn tls_key() -> tls::Key {
151153
}
152154
}
153155

154-
#[fixed_stack_segment]
155-
#[inline(never)]
156-
fn maybe_tls_key() -> Option<tls::Key> {
156+
#[inline]
157+
#[cfg(not(test))]
158+
pub fn maybe_tls_key() -> Option<tls::Key> {
157159
unsafe {
158-
let key: *mut c_void = rust_get_rt_tls_key();
159-
let key: &mut tls::Key = cast::transmute(key);
160-
let key = *key;
161-
// Check that the key has been initialized.
162-
163160
// NB: This is a little racy because, while the key is
164161
// initalized under a mutex and it's assumed to be initalized
165162
// in the Scheduler ctor by any thread that needs to use it,
@@ -170,14 +167,19 @@ fn maybe_tls_key() -> Option<tls::Key> {
170167
// another thread. I think this is fine since the only action
171168
// they could take if it was initialized would be to check the
172169
// thread-local value and see that it's not set.
173-
if key != -1 {
174-
return Some(key);
170+
if RT_TLS_KEY != -1 {
171+
return Some(RT_TLS_KEY);
175172
} else {
176173
return None;
177174
}
178175
}
176+
}
179177

180-
extern {
181-
fn rust_get_rt_tls_key() -> *mut c_void;
182-
}
178+
// XXX: The boundary between the running runtime and the testing runtime
179+
// seems to be fuzzy at the moment, and trying to use two different keys
180+
// results in disaster. This should not be necessary.
181+
#[inline]
182+
#[cfg(test)]
183+
pub fn maybe_tls_key() -> Option<tls::Key> {
184+
unsafe { ::cast::transmute(::realstd::rt::local_ptr::maybe_tls_key()) }
183185
}

src/rt/rust_builtin.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -447,19 +447,14 @@ rust_readdir() {
447447
#endif
448448

449449
#ifndef _WIN32
450-
pthread_key_t rt_key = -1;
450+
typedef pthread_key_t tls_key;
451451
#else
452-
DWORD rt_key = -1;
452+
typedef DWORD tls_key;
453453
#endif
454454

455-
extern "C" void*
456-
rust_get_rt_tls_key() {
457-
return &rt_key;
458-
}
459-
460455
// Initialize the TLS key used by the new scheduler
461456
extern "C" CDECL void
462-
rust_initialize_rt_tls_key() {
457+
rust_initialize_rt_tls_key(tls_key *key) {
463458

464459
static lock_and_signal init_lock;
465460
static bool initialized = false;
@@ -469,10 +464,10 @@ rust_initialize_rt_tls_key() {
469464
if (!initialized) {
470465

471466
#ifndef _WIN32
472-
assert(!pthread_key_create(&rt_key, NULL));
467+
assert(!pthread_key_create(key, NULL));
473468
#else
474-
rt_key = TlsAlloc();
475-
assert(rt_key != TLS_OUT_OF_INDEXES);
469+
*key = TlsAlloc();
470+
assert(*key != TLS_OUT_OF_INDEXES);
476471
#endif
477472

478473
initialized = true;

src/rt/rustrt.def.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ linenoiseHistoryLoad
143143
rust_raw_thread_start
144144
rust_raw_thread_join
145145
rust_raw_thread_delete
146-
rust_get_rt_tls_key
147146
swap_registers
148147
rust_readdir
149148
rust_opendir

0 commit comments

Comments
 (0)