about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-11-06 01:17:04 -0500
committerDaniel Micay <danielmicay@gmail.com>2013-11-26 14:49:14 -0500
commit2cf3d8adf2cbdf760063a247162a558e68fe35fd (patch)
treec27a0ee3f736976bb1bb4074cb28ebafad708b1d /src/libstd/rt
parent1795ae4e8a472ce500660fa59abf61114f5ef8c9 (diff)
downloadrust-2cf3d8adf2cbdf760063a247162a558e68fe35fd.tar.gz
rust-2cf3d8adf2cbdf760063a247162a558e68fe35fd.zip
port the runtime to `#[thread_local]`
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/local_ptr.rs106
-rw-r--r--src/libstd/rt/mod.rs4
2 files changed, 105 insertions, 5 deletions
diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs
index 862ecd6499a..d840a6b2ff3 100644
--- a/src/libstd/rt/local_ptr.rs
+++ b/src/libstd/rt/local_ptr.rs
@@ -17,16 +17,35 @@
 
 use libc::c_void;
 use cast;
+#[cfg(stage0)]
+#[cfg(windows)]
 use ptr;
 use cell::Cell;
 use option::{Option, Some, None};
 use unstable::finally::Finally;
+#[cfg(stage0)]
+#[cfg(windows)]
 use unstable::mutex::{Mutex, MUTEX_INIT};
+#[cfg(stage0)]
+#[cfg(windows)]
 use tls = rt::thread_local_storage;
 
+#[cfg(not(stage0), not(windows), test)]
+#[thread_local]
+pub use realstd::rt::shouldnt_be_public::RT_TLS_PTR;
+
+#[cfg(not(stage0), not(windows), not(test))]
+#[thread_local]
+pub static mut RT_TLS_PTR: *mut c_void = 0 as *mut c_void;
+
+#[cfg(stage0)]
+#[cfg(windows)]
 static mut RT_TLS_KEY: tls::Key = -1;
 
 /// Initialize the TLS key. Other ops will fail if this isn't executed first.
+#[inline(never)]
+#[cfg(stage0)]
+#[cfg(windows)]
 pub fn init_tls_key() {
     static mut lock: Mutex = MUTEX_INIT;
     static mut initialized: bool = false;
@@ -41,24 +60,42 @@ pub fn init_tls_key() {
     }
 }
 
+#[cfg(not(stage0), not(windows))]
+pub fn init_tls_key() {}
+
 /// Give a pointer to thread-local storage.
 ///
 /// # Safety note
 ///
 /// Does not validate the pointer type.
 #[inline]
+#[cfg(stage0)]
+#[cfg(windows)]
 pub unsafe fn put<T>(sched: ~T) {
     let key = tls_key();
     let void_ptr: *mut c_void = cast::transmute(sched);
     tls::set(key, void_ptr);
 }
 
+/// Give a pointer to thread-local storage.
+///
+/// # Safety note
+///
+/// Does not validate the pointer type.
+#[inline]
+#[cfg(not(stage0), not(windows))]
+pub unsafe fn put<T>(sched: ~T) {
+    RT_TLS_PTR = cast::transmute(sched)
+}
+
 /// Take ownership of a pointer from thread-local storage.
 ///
 /// # Safety note
 ///
 /// Does not validate the pointer type.
 #[inline]
+#[cfg(stage0)]
+#[cfg(windows)]
 pub unsafe fn take<T>() -> ~T {
     let key = tls_key();
     let void_ptr: *mut c_void = tls::get(key);
@@ -75,8 +112,23 @@ pub unsafe fn take<T>() -> ~T {
 /// # Safety note
 ///
 /// Does not validate the pointer type.
+#[inline]
+#[cfg(not(stage0), not(windows))]
+pub unsafe fn take<T>() -> ~T {
+    let ptr: ~T = cast::transmute(RT_TLS_PTR);
+    RT_TLS_PTR = cast::transmute(0); // can't use `as`, due to type not matching with `cfg(test)`
+    ptr
+}
+
+/// Take ownership of a pointer from thread-local storage.
+///
+/// # Safety note
+///
+/// Does not validate the pointer type.
 /// Leaves the old pointer in TLS for speed.
 #[inline]
+#[cfg(stage0)]
+#[cfg(windows)]
 pub unsafe fn unsafe_take<T>() -> ~T {
     let key = tls_key();
     let void_ptr: *mut c_void = tls::get(key);
@@ -87,7 +139,21 @@ pub unsafe fn unsafe_take<T>() -> ~T {
     return ptr;
 }
 
+/// Take ownership of a pointer from thread-local storage.
+///
+/// # Safety note
+///
+/// Does not validate the pointer type.
+/// Leaves the old pointer in TLS for speed.
+#[inline]
+#[cfg(not(stage0), not(windows))]
+pub unsafe fn unsafe_take<T>() -> ~T {
+    cast::transmute(RT_TLS_PTR)
+}
+
 /// Check whether there is a thread-local pointer installed.
+#[cfg(stage0)]
+#[cfg(windows)]
 pub fn exists() -> bool {
     unsafe {
         match maybe_tls_key() {
@@ -97,6 +163,14 @@ pub fn exists() -> bool {
     }
 }
 
+/// Check whether there is a thread-local pointer installed.
+#[cfg(not(stage0), not(windows))]
+pub fn exists() -> bool {
+    unsafe {
+        RT_TLS_PTR.is_not_null()
+    }
+}
+
 /// Borrow the thread-local value from thread-local storage.
 /// While the value is borrowed it is not available in TLS.
 ///
@@ -123,6 +197,8 @@ pub unsafe fn borrow<T>(f: |&mut T|) {
 ///
 /// Because this leaves the value in thread-local storage it is possible
 /// For the Scheduler pointer to be aliased
+#[cfg(stage0)]
+#[cfg(windows)]
 pub unsafe fn unsafe_borrow<T>() -> *mut T {
     let key = tls_key();
     let void_ptr = tls::get(key);
@@ -132,6 +208,16 @@ pub unsafe fn unsafe_borrow<T>() -> *mut T {
     void_ptr as *mut T
 }
 
+#[cfg(not(stage0), not(windows))]
+pub unsafe fn unsafe_borrow<T>() -> *mut T {
+    if RT_TLS_PTR.is_null() {
+        rtabort!("thread-local pointer is null. bogus!");
+    }
+    RT_TLS_PTR as *mut T
+}
+
+#[cfg(stage0)]
+#[cfg(windows)]
 pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
     match maybe_tls_key() {
         Some(key) => {
@@ -146,7 +232,18 @@ pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
     }
 }
 
+#[cfg(not(stage0), not(windows))]
+pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
+    if RT_TLS_PTR.is_null() {
+        None
+    } else {
+        Some(RT_TLS_PTR as *mut T)
+    }
+}
+
 #[inline]
+#[cfg(stage0)]
+#[cfg(windows)]
 fn tls_key() -> tls::Key {
     match maybe_tls_key() {
         Some(key) => key,
@@ -155,7 +252,8 @@ fn tls_key() -> tls::Key {
 }
 
 #[inline]
-#[cfg(not(test))]
+#[cfg(not(test), stage0)]
+#[cfg(not(test), windows)]
 pub fn maybe_tls_key() -> Option<tls::Key> {
     unsafe {
         // NB: This is a little racy because, while the key is
@@ -176,11 +274,9 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
     }
 }
 
-// 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)]
+#[cfg(test, stage0)]
+#[cfg(test, windows)]
 pub fn maybe_tls_key() -> Option<tls::Key> {
     unsafe { ::cast::transmute(::realstd::rt::shouldnt_be_public::maybe_tls_key()) }
 }
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index ad5c69e9a0c..1d2742fd029 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -95,7 +95,11 @@ pub use self::kill::BlockedTask;
 pub mod shouldnt_be_public {
     pub use super::select::SelectInner;
     pub use super::select::{SelectInner, SelectPortInner};
+    #[cfg(stage0)]
+    #[cfg(windows)]
     pub use super::local_ptr::maybe_tls_key;
+    #[cfg(not(stage0), not(windows))]
+    pub use super::local_ptr::RT_TLS_PTR;
 }
 
 // Internal macros used by the runtime.