Skip to content

Commit 71aa6b6

Browse files
committed
core::rt: Move more TLS functionality into local_ptr
1 parent 97c2fd1 commit 71aa6b6

File tree

2 files changed

+94
-58
lines changed

2 files changed

+94
-58
lines changed

src/libcore/rt/local_ptr.rs

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Access to a single thread-local pointer
11+
//! Access to a single thread-local pointer.
12+
//!
13+
//! The runtime will use this for storing ~Task.
14+
//!
15+
//! XXX: Add runtime checks for usage of inconsistent pointer types.
16+
//! and for overwriting an existing pointer.
1217
1318
use libc::c_void;
1419
use cast;
20+
use ptr;
21+
use cell::Cell;
1522
use option::{Option, Some, None};
23+
use unstable::finally::Finally;
1624
use tls = rt::thread_local_storage;
1725

1826
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
@@ -25,14 +33,87 @@ pub fn init_tls_key() {
2533
}
2634
}
2735

28-
pub fn tls_key() -> tls::Key {
36+
/// Give a pointer to thread-local storage.
37+
///
38+
/// # Safety note
39+
///
40+
/// Does not validate the pointer type.
41+
pub unsafe fn put<T>(sched: ~T) {
42+
let key = tls_key();
43+
let void_ptr: *mut c_void = cast::transmute(sched);
44+
tls::set(key, void_ptr);
45+
}
46+
47+
/// Take ownership of a pointer from thread-local storage.
48+
///
49+
/// # Safety note
50+
///
51+
/// Does not validate the pointer type.
52+
pub unsafe fn take<T>() -> ~T {
53+
let key = tls_key();
54+
let void_ptr: *mut c_void = tls::get(key);
55+
rtassert!(void_ptr.is_not_null());
56+
let ptr: ~T = cast::transmute(void_ptr);
57+
tls::set(key, ptr::mut_null());
58+
return ptr;
59+
}
60+
61+
/// Check whether there is a thread-local pointer installed.
62+
pub fn exists() -> bool {
63+
unsafe {
64+
match maybe_tls_key() {
65+
Some(key) => tls::get(key).is_not_null(),
66+
None => false
67+
}
68+
}
69+
}
70+
71+
/// Borrow the thread-local scheduler from thread-local storage.
72+
/// While the scheduler is borrowed it is not available in TLS.
73+
///
74+
/// # Safety note
75+
///
76+
/// Does not validate the pointer type.
77+
pub unsafe fn borrow<T>(f: &fn(&mut T)) {
78+
let mut value = take();
79+
80+
// XXX: Need a different abstraction from 'finally' here to avoid unsafety
81+
let unsafe_ptr = cast::transmute_mut_region(&mut *value);
82+
let value_cell = Cell(value);
83+
84+
do (|| {
85+
f(unsafe_ptr);
86+
}).finally {
87+
put(value_cell.take());
88+
}
89+
}
90+
91+
/// Borrow a mutable reference to the thread-local Scheduler
92+
///
93+
/// # Safety Note
94+
///
95+
/// Because this leaves the Scheduler in thread-local storage it is possible
96+
/// For the Scheduler pointer to be aliased
97+
pub unsafe fn unsafe_borrow<T>() -> *mut T {
98+
let key = tls_key();
99+
let mut void_sched: *mut c_void = tls::get(key);
100+
rtassert!(void_sched.is_not_null());
101+
{
102+
let sched: *mut *mut c_void = &mut void_sched;
103+
let sched: *mut ~T = sched as *mut ~T;
104+
let sched: *mut T = &mut **sched;
105+
return sched;
106+
}
107+
}
108+
109+
fn tls_key() -> tls::Key {
29110
match maybe_tls_key() {
30111
Some(key) => key,
31112
None => abort!("runtime tls key not initialized")
32113
}
33114
}
34115

35-
pub fn maybe_tls_key() -> Option<tls::Key> {
116+
fn maybe_tls_key() -> Option<tls::Key> {
36117
unsafe {
37118
let key: *mut c_void = rust_get_rt_tls_key();
38119
let key: &mut tls::Key = cast::transmute(key);
@@ -55,9 +136,10 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
55136
return None;
56137
}
57138
}
58-
}
59139

60-
extern {
61-
#[fast_ffi]
62-
fn rust_get_rt_tls_key() -> *mut c_void;
140+
extern {
141+
#[fast_ffi]
142+
fn rust_get_rt_tls_key() -> *mut c_void;
143+
}
144+
63145
}

src/libcore/rt/local_sched.rs

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,71 +25,25 @@ use tls = rt::thread_local_storage;
2525
#[cfg(test)] use rt::uv::uvio::UvEventLoop;
2626

2727
/// Give the Scheduler to thread-local storage
28-
pub fn put(sched: ~Scheduler) {
29-
unsafe {
30-
let key = local_ptr::tls_key();
31-
let void_sched: *mut c_void = cast::transmute(sched);
32-
tls::set(key, void_sched);
33-
}
34-
}
28+
pub fn put(sched: ~Scheduler) { unsafe { local_ptr::put(sched) } }
3529

3630
/// Take ownership of the Scheduler from thread-local storage
37-
pub fn take() -> ~Scheduler {
38-
unsafe {
39-
let key = local_ptr::tls_key();
40-
let void_sched: *mut c_void = tls::get(key);
41-
rtassert!(void_sched.is_not_null());
42-
let sched: ~Scheduler = cast::transmute(void_sched);
43-
tls::set(key, mut_null());
44-
return sched;
45-
}
46-
}
31+
pub fn take() -> ~Scheduler { unsafe { local_ptr::take() } }
4732

4833
/// Check whether there is a thread-local Scheduler attached to the running thread
49-
pub fn exists() -> bool {
50-
unsafe {
51-
match local_ptr::maybe_tls_key() {
52-
Some(key) => tls::get(key).is_not_null(),
53-
None => false
54-
}
55-
}
56-
}
34+
pub fn exists() -> bool { local_ptr::exists() }
5735

5836
/// Borrow the thread-local scheduler from thread-local storage.
5937
/// While the scheduler is borrowed it is not available in TLS.
60-
pub fn borrow(f: &fn(&mut Scheduler)) {
61-
let mut sched = take();
62-
63-
// XXX: Need a different abstraction from 'finally' here to avoid unsafety
64-
unsafe {
65-
let unsafe_sched = cast::transmute_mut_region(&mut *sched);
66-
let sched = Cell(sched);
67-
68-
do (|| {
69-
f(unsafe_sched);
70-
}).finally {
71-
put(sched.take());
72-
}
73-
}
74-
}
38+
pub fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } }
7539

7640
/// Borrow a mutable reference to the thread-local Scheduler
7741
///
7842
/// # Safety Note
7943
///
8044
/// Because this leaves the Scheduler in thread-local storage it is possible
8145
/// For the Scheduler pointer to be aliased
82-
pub unsafe fn unsafe_borrow() -> *mut Scheduler {
83-
let key = local_ptr::tls_key();
84-
let mut void_sched: *mut c_void = tls::get(key);
85-
rtassert!(void_sched.is_not_null());
86-
{
87-
let sched: *mut *mut c_void = &mut void_sched;
88-
let sched: *mut ~Scheduler = sched as *mut ~Scheduler;
89-
let sched: *mut Scheduler = &mut **sched;
90-
return sched;
91-
}
92-
}
46+
pub unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() }
9347

9448
pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject {
9549
let sched = unsafe_borrow();

0 commit comments

Comments
 (0)