Skip to content

Commit 97c2fd1

Browse files
committed
core::rt: Move some TLS functions from local_sched to local_ptr
1 parent 86ba457 commit 97c2fd1

File tree

4 files changed

+82
-59
lines changed

4 files changed

+82
-59
lines changed

src/libcore/rt/local_ptr.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Access to a single thread-local pointer
12+
13+
use libc::c_void;
14+
use cast;
15+
use option::{Option, Some, None};
16+
use tls = rt::thread_local_storage;
17+
18+
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
19+
pub fn init_tls_key() {
20+
unsafe {
21+
rust_initialize_rt_tls_key();
22+
extern {
23+
fn rust_initialize_rt_tls_key();
24+
}
25+
}
26+
}
27+
28+
pub fn tls_key() -> tls::Key {
29+
match maybe_tls_key() {
30+
Some(key) => key,
31+
None => abort!("runtime tls key not initialized")
32+
}
33+
}
34+
35+
pub fn maybe_tls_key() -> Option<tls::Key> {
36+
unsafe {
37+
let key: *mut c_void = rust_get_rt_tls_key();
38+
let key: &mut tls::Key = cast::transmute(key);
39+
let key = *key;
40+
// Check that the key has been initialized.
41+
42+
// NB: This is a little racy because, while the key is
43+
// initalized under a mutex and it's assumed to be initalized
44+
// in the Scheduler ctor by any thread that needs to use it,
45+
// we are not accessing the key under a mutex. Threads that
46+
// are not using the new Scheduler but still *want to check*
47+
// whether they are running under a new Scheduler may see a 0
48+
// value here that is in the process of being initialized in
49+
// another thread. I think this is fine since the only action
50+
// they could take if it was initialized would be to check the
51+
// thread-local value and see that it's not set.
52+
if key != -1 {
53+
return Some(key);
54+
} else {
55+
return None;
56+
}
57+
}
58+
}
59+
60+
extern {
61+
#[fast_ffi]
62+
fn rust_get_rt_tls_key() -> *mut c_void;
63+
}

src/libcore/rt/local_sched.rs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,16 @@ use cell::Cell;
1818

1919
use rt::sched::Scheduler;
2020
use rt::rtio::{EventLoop, IoFactoryObject};
21-
use tls = rt::thread_local_storage;
2221
use unstable::finally::Finally;
22+
use rt::local_ptr;
23+
use tls = rt::thread_local_storage;
2324

2425
#[cfg(test)] use rt::uv::uvio::UvEventLoop;
2526

26-
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
27-
pub fn init_tls_key() {
28-
unsafe {
29-
rust_initialize_rt_tls_key();
30-
extern {
31-
fn rust_initialize_rt_tls_key();
32-
}
33-
}
34-
}
35-
3627
/// Give the Scheduler to thread-local storage
3728
pub fn put(sched: ~Scheduler) {
3829
unsafe {
39-
let key = tls_key();
30+
let key = local_ptr::tls_key();
4031
let void_sched: *mut c_void = cast::transmute(sched);
4132
tls::set(key, void_sched);
4233
}
@@ -45,7 +36,7 @@ pub fn put(sched: ~Scheduler) {
4536
/// Take ownership of the Scheduler from thread-local storage
4637
pub fn take() -> ~Scheduler {
4738
unsafe {
48-
let key = tls_key();
39+
let key = local_ptr::tls_key();
4940
let void_sched: *mut c_void = tls::get(key);
5041
rtassert!(void_sched.is_not_null());
5142
let sched: ~Scheduler = cast::transmute(void_sched);
@@ -57,7 +48,7 @@ pub fn take() -> ~Scheduler {
5748
/// Check whether there is a thread-local Scheduler attached to the running thread
5849
pub fn exists() -> bool {
5950
unsafe {
60-
match maybe_tls_key() {
51+
match local_ptr::maybe_tls_key() {
6152
Some(key) => tls::get(key).is_not_null(),
6253
None => false
6354
}
@@ -89,7 +80,7 @@ pub fn borrow(f: &fn(&mut Scheduler)) {
8980
/// Because this leaves the Scheduler in thread-local storage it is possible
9081
/// For the Scheduler pointer to be aliased
9182
pub unsafe fn unsafe_borrow() -> *mut Scheduler {
92-
let key = tls_key();
83+
let key = local_ptr::tls_key();
9384
let mut void_sched: *mut c_void = tls::get(key);
9485
rtassert!(void_sched.is_not_null());
9586
{
@@ -106,43 +97,6 @@ pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject {
10697
return io;
10798
}
10899

109-
fn tls_key() -> tls::Key {
110-
match maybe_tls_key() {
111-
Some(key) => key,
112-
None => abort!("runtime tls key not initialized")
113-
}
114-
}
115-
116-
fn maybe_tls_key() -> Option<tls::Key> {
117-
unsafe {
118-
let key: *mut c_void = rust_get_rt_tls_key();
119-
let key: &mut tls::Key = cast::transmute(key);
120-
let key = *key;
121-
// Check that the key has been initialized.
122-
123-
// NB: This is a little racy because, while the key is
124-
// initalized under a mutex and it's assumed to be initalized
125-
// in the Scheduler ctor by any thread that needs to use it,
126-
// we are not accessing the key under a mutex. Threads that
127-
// are not using the new Scheduler but still *want to check*
128-
// whether they are running under a new Scheduler may see a 0
129-
// value here that is in the process of being initialized in
130-
// another thread. I think this is fine since the only action
131-
// they could take if it was initialized would be to check the
132-
// thread-local value and see that it's not set.
133-
if key != -1 {
134-
return Some(key);
135-
} else {
136-
return None;
137-
}
138-
}
139-
}
140-
141-
extern {
142-
#[fast_ffi]
143-
fn rust_get_rt_tls_key() -> *mut c_void;
144-
}
145-
146100
#[test]
147101
fn thread_local_scheduler_smoke_test() {
148102
let scheduler = ~UvEventLoop::new_scheduler();

src/libcore/rt/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,6 @@ pub mod uv;
8585
/// or task-local storage.
8686
pub mod local;
8787

88-
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
89-
/// Bindings to pthread/windows thread-local storage.
90-
pub mod thread_local_storage;
91-
9288
/// A parallel work-stealing deque.
9389
mod work_queue;
9490

@@ -126,6 +122,15 @@ pub mod tube;
126122
/// Simple reimplementation of core::comm
127123
pub mod comm;
128124

125+
// FIXME #5248 shouldn't be pub
126+
/// The runtime needs to be able to put a pointer into thread-local storage.
127+
pub mod local_ptr;
128+
129+
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
130+
/// Bindings to pthread/windows thread-local storage.
131+
pub mod thread_local_storage;
132+
133+
129134
/// Set up a default runtime configuration, given compiler-supplied arguments.
130135
///
131136
/// This is invoked by the `start` _language item_ (unstable::lang) to

src/libcore/rt/sched.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
use option::*;
1212
use sys;
1313
use cast::transmute;
14+
use cell::Cell;
1415

1516
use super::work_queue::WorkQueue;
1617
use super::stack::{StackPool, StackSegment};
1718
use super::rtio::{EventLoop, EventLoopObject};
1819
use super::context::Context;
1920
use super::task::Task;
20-
use cell::Cell;
21+
use rt::local_ptr;
2122

2223
// A more convenient name for external callers, e.g. `local_sched::take()`
2324
pub mod local_sched;
@@ -64,8 +65,8 @@ pub impl Scheduler {
6465

6566
fn new(event_loop: ~EventLoopObject) -> Scheduler {
6667

67-
// Lazily initialize the scheduler TLS key
68-
local_sched::init_tls_key();
68+
// Lazily initialize the runtime TLS key
69+
local_ptr::init_tls_key();
6970

7071
Scheduler {
7172
event_loop: event_loop,

0 commit comments

Comments
 (0)