Skip to content

Commit 01e8378

Browse files
committed
Update to new sys requirements
1 parent 74dc845 commit 01e8378

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2014-2015 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+
#![cfg(target_thread_local)]
12+
#![unstable(feature = "thread_local_internals", issue = "0")]
13+
14+
use cell::{Cell, UnsafeCell};
15+
use intrinsics;
16+
use ptr;
17+
18+
pub struct Key<T> {
19+
inner: UnsafeCell<Option<T>>,
20+
21+
// Metadata to keep track of the state of the destructor. Remember that
22+
// these variables are thread-local, not global.
23+
dtor_registered: Cell<bool>,
24+
dtor_running: Cell<bool>,
25+
}
26+
27+
unsafe impl<T> ::marker::Sync for Key<T> { }
28+
29+
impl<T> Key<T> {
30+
pub const fn new() -> Key<T> {
31+
Key {
32+
inner: UnsafeCell::new(None),
33+
dtor_registered: Cell::new(false),
34+
dtor_running: Cell::new(false)
35+
}
36+
}
37+
38+
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
39+
unsafe {
40+
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
41+
return None
42+
}
43+
self.register_dtor();
44+
}
45+
Some(&self.inner)
46+
}
47+
48+
unsafe fn register_dtor(&self) {
49+
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
50+
return
51+
}
52+
53+
register_dtor(self as *const _ as *mut u8,
54+
destroy_value::<T>);
55+
self.dtor_registered.set(true);
56+
}
57+
}
58+
59+
unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
60+
// The fallback implementation uses a vanilla OS-based TLS key to track
61+
// the list of destructors that need to be run for this thread. The key
62+
// then has its own destructor which runs all the other destructors.
63+
//
64+
// The destructor for DTORS is a little special in that it has a `while`
65+
// loop to continuously drain the list of registered destructors. It
66+
// *should* be the case that this loop always terminates because we
67+
// provide the guarantee that a TLS key cannot be set after it is
68+
// flagged for destruction.
69+
use sys_common::thread_local as os;
70+
71+
static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
72+
type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
73+
if DTORS.get().is_null() {
74+
let v: Box<List> = box Vec::new();
75+
DTORS.set(Box::into_raw(v) as *mut u8);
76+
}
77+
let list: &mut List = &mut *(DTORS.get() as *mut List);
78+
list.push((t, dtor));
79+
80+
unsafe extern fn run_dtors(mut ptr: *mut u8) {
81+
while !ptr.is_null() {
82+
let list: Box<List> = Box::from_raw(ptr as *mut List);
83+
for &(ptr, dtor) in list.iter() {
84+
dtor(ptr);
85+
}
86+
ptr = DTORS.get();
87+
DTORS.set(ptr::null_mut());
88+
}
89+
}
90+
}
91+
92+
pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
93+
let ptr = ptr as *mut Key<T>;
94+
// Right before we run the user destructor be sure to flag the
95+
// destructor as running for this thread so calls to `get` will return
96+
// `None`.
97+
(*ptr).dtor_running.set(true);
98+
99+
// The OSX implementation of TLS apparently had an odd aspect to it
100+
// where the pointer we have may be overwritten while this destructor
101+
// is running. Specifically if a TLS destructor re-accesses TLS it may
102+
// trigger a re-initialization of all TLS variables, paving over at
103+
// least some destroyed ones with initial values.
104+
//
105+
// This means that if we drop a TLS value in place on OSX that we could
106+
// revert the value to its original state halfway through the
107+
// destructor, which would be bad!
108+
//
109+
// Hence, we use `ptr::read` on OSX (to move to a "safe" location)
110+
// instead of drop_in_place.
111+
if cfg!(target_os = "macos") {
112+
ptr::read((*ptr).inner.get());
113+
} else {
114+
ptr::drop_in_place((*ptr).inner.get());
115+
}
116+
}

src/libstd/sys/redox/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod backtrace;
88
pub mod condvar;
99
pub mod env;
1010
pub mod ext;
11+
pub mod fast_thread_local;
1112
pub mod fd;
1213
pub mod fs;
1314
pub mod memchr;
@@ -76,3 +77,8 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
7677
pub fn cvt(result: Result<usize, libc::Error>) -> io::Result<usize> {
7778
result.map_err(|err| io::Error::from_raw_os_error(err.errno as i32))
7879
}
80+
81+
/// On Redox, use an illegal instruction to abort
82+
pub unsafe fn abort_internal() -> ! {
83+
::core::intrinsics::abort();
84+
}

src/libstd/sys/redox/stdio.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,4 @@ impl io::Write for Stderr {
6767
}
6868

6969
pub const EBADF_ERR: i32 = ::libc::EBADF;
70+
pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;

0 commit comments

Comments
 (0)