about summary refs log tree commit diff
path: root/src/libstd/thread
diff options
context:
space:
mode:
authorMathieu David <mathieudavid@mathieudavid.org>2015-07-27 20:46:01 +0200
committerMathieu David <mathieudavid@mathieudavid.org>2015-07-27 20:46:01 +0200
commitf6e9240a99e86d2c799dc29f179dd2870e51f71d (patch)
treea7e5ba20745b16949a45a4612b2708e262693a7b /src/libstd/thread
parent003c3eaa62981b791f9eb7bcad015baa1e00d98c (diff)
parent3351afeecffcc9ebaeb1188a5cde976da8e4a5aa (diff)
downloadrust-f6e9240a99e86d2c799dc29f179dd2870e51f71d.tar.gz
rust-f6e9240a99e86d2c799dc29f179dd2870e51f71d.zip
Fix the relative path issue by including the files using include_bytes!
Diffstat (limited to 'src/libstd/thread')
-rw-r--r--src/libstd/thread/local.rs25
-rw-r--r--src/libstd/thread/mod.rs85
-rw-r--r--src/libstd/thread/scoped_tls.rs3
3 files changed, 70 insertions, 43 deletions
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 60563340d10..11b375dcce2 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -275,6 +275,7 @@ mod imp {
 
     use cell::{Cell, UnsafeCell};
     use intrinsics;
+    use ptr;
 
     pub struct Key<T> {
         inner: UnsafeCell<Option<T>>,
@@ -327,7 +328,6 @@ mod imp {
     #[cfg(target_os = "linux")]
     unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
         use mem;
-        use ptr;
         use libc;
         use sys_common::thread_local as os;
 
@@ -335,13 +335,13 @@ mod imp {
             #[linkage = "extern_weak"]
             static __dso_handle: *mut u8;
             #[linkage = "extern_weak"]
-            static __cxa_thread_atexit_impl: *const ();
+            static __cxa_thread_atexit_impl: *const libc::c_void;
         }
         if !__cxa_thread_atexit_impl.is_null() {
             type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
                                       arg: *mut u8,
                                       dso_handle: *mut u8) -> libc::c_int;
-            mem::transmute::<*const (), F>(__cxa_thread_atexit_impl)
+            mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)
             (dtor, t, &__dso_handle as *const _ as *mut _);
             return
         }
@@ -394,7 +394,24 @@ mod imp {
         // destructor as running for this thread so calls to `get` will return
         // `None`.
         (*ptr).dtor_running.set(true);
-        intrinsics::drop_in_place((*ptr).inner.get());
+
+        // The OSX implementation of TLS apparently had an odd aspect to it
+        // where the pointer we have may be overwritten while this destructor
+        // is running. Specifically if a TLS destructor re-accesses TLS it may
+        // trigger a re-initialization of all TLS variables, paving over at
+        // least some destroyed ones with initial values.
+        //
+        // This means that if we drop a TLS value in place on OSX that we could
+        // revert the value to its original state halfway through the
+        // destructor, which would be bad!
+        //
+        // Hence, we use `ptr::read` on OSX (to move to a "safe" location)
+        // instead of drop_in_place.
+        if cfg!(target_os = "macos") {
+            ptr::read((*ptr).inner.get());
+        } else {
+            intrinsics::drop_in_place((*ptr).inner.get());
+        }
     }
 }
 
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index dbb7d3233bc..3388968c56c 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -85,33 +85,6 @@
 //! value produced by the child thread, or `Err` of the value given to
 //! a call to `panic!` if the child panicked.
 //!
-//! ## Scoped threads
-//!
-//! The `spawn` method does not allow the child and parent threads to
-//! share any stack data, since that is not safe in general. However,
-//! `scoped` makes it possible to share the parent's stack by forcing
-//! a join before any relevant stack frames are popped:
-//!
-//! ```rust
-//! # #![feature(scoped)]
-//! use std::thread;
-//!
-//! let guard = thread::scoped(move || {
-//!     // some work here
-//! });
-//!
-//! // do some other work in the meantime
-//! let output = guard.join();
-//! ```
-//!
-//! The `scoped` function doesn't return a `Thread` directly; instead,
-//! it returns a *join guard*. The join guard is an RAII-style guard
-//! that will automatically join the child thread (block until it
-//! terminates) when it is dropped. You can join the child thread in
-//! advance by calling the `join` method on the guard, which will also
-//! return the result produced by the thread.  A handle to the thread
-//! itself is available via the `thread` method of the join guard.
-//!
 //! ## Configuring threads
 //!
 //! A new thread can be configured before it is spawned via the `Builder` type,
@@ -288,7 +261,7 @@ impl Builder {
     /// upon being dropped. Because the child thread may refer to data on the
     /// current thread's stack (hence the "scoped" name), it cannot be detached;
     /// it *must* be joined before the relevant stack frame is popped. See the
-    /// module documentation for additional details.
+    /// documentation on `thread::scoped` for additional details.
     ///
     /// # Errors
     ///
@@ -388,12 +361,30 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
 
 /// Spawns a new *scoped* thread, returning a `JoinGuard` for it.
 ///
-/// The join guard can be used to explicitly join the child thread (via
-/// `join`), returning `Result<T>`, or it will implicitly join the child
-/// upon being dropped. Because the child thread may refer to data on the
-/// current thread's stack (hence the "scoped" name), it cannot be detached;
-/// it *must* be joined before the relevant stack frame is popped. See the
-/// module documentation for additional details.
+/// The `spawn` method does not allow the child and parent threads to
+/// share any stack data, since that is not safe in general. However,
+/// `scoped` makes it possible to share the parent's stack by forcing
+/// a join before any relevant stack frames are popped:
+///
+/// ```rust
+/// # #![feature(scoped)]
+/// use std::thread;
+///
+/// let guard = thread::scoped(move || {
+///     // some work here
+/// });
+///
+/// // do some other work in the meantime
+/// let output = guard.join();
+/// ```
+///
+/// The `scoped` function doesn't return a `Thread` directly; instead, it
+/// returns a *join guard*. The join guard can be used to explicitly join
+/// the child thread (via `join`), returning `Result<T>`, or it will
+/// implicitly join the child upon being dropped. Because the child thread
+/// may refer to data on the current thread's stack (hence the "scoped"
+/// name), it cannot be detached; it *must* be joined before the relevant
+/// stack frame is popped.
 ///
 /// # Panics
 ///
@@ -434,9 +425,9 @@ pub fn panicking() -> bool {
 
 /// Invokes a closure, capturing the cause of panic if one occurs.
 ///
-/// This function will return `Ok(())` if the closure does not panic, and will
-/// return `Err(cause)` if the closure panics. The `cause` returned is the
-/// object with which panic was originally invoked.
+/// This function will return `Ok` with the closure's result if the closure
+/// does not panic, and will return `Err(cause)` if the closure panics. The
+/// `cause` returned is the object with which panic was originally invoked.
 ///
 /// It is currently undefined behavior to unwind from Rust code into foreign
 /// code, so this function is particularly useful when Rust is called from
@@ -508,9 +499,25 @@ pub fn sleep(dur: Duration) {
     imp::Thread::sleep(dur)
 }
 
-/// Blocks unless or until the current thread's token is made available (may wake spuriously).
+/// Blocks unless or until the current thread's token is made available.
 ///
-/// See the module doc for more detail.
+/// Every thread is equipped with some basic low-level blocking support, via
+/// the `park()` function and the [`unpark()`][unpark] method. These can be
+/// used as a more CPU-efficient implementation of a spinlock.
+///
+/// [unpark]: struct.Thread.html#method.unpark
+///
+/// The API is typically used by acquiring a handle to the current thread,
+/// placing that handle in a shared data structure so that other threads can
+/// find it, and then parking (in a loop with a check for the token actually
+/// being acquired).
+///
+/// A call to `park` does not guarantee that the thread will remain parked
+/// forever, and callers should be prepared for this possibility.
+///
+/// See the [module documentation][thread] for more detail.
+///
+/// [thread]: index.html
 //
 // The implementation currently uses the trivial strategy of a Mutex+Condvar
 // with wakeup flag, which does not actually allow spurious wakeups. In the
diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs
index 679902ec7ab..c2fad0aa89c 100644
--- a/src/libstd/thread/scoped_tls.rs
+++ b/src/libstd/thread/scoped_tls.rs
@@ -104,6 +104,7 @@ macro_rules! __scoped_thread_local_inner {
         #[cfg_attr(not(any(windows,
                            target_os = "android",
                            target_os = "ios",
+                           target_os = "netbsd",
                            target_os = "openbsd",
                            target_arch = "aarch64")),
                    thread_local)]
@@ -215,6 +216,7 @@ impl<T> ScopedKey<T> {
 #[cfg(not(any(windows,
               target_os = "android",
               target_os = "ios",
+              target_os = "netbsd",
               target_os = "openbsd",
               target_arch = "aarch64",
               no_elf_tls)))]
@@ -238,6 +240,7 @@ mod imp {
 #[cfg(any(windows,
           target_os = "android",
           target_os = "ios",
+          target_os = "netbsd",
           target_os = "openbsd",
           target_arch = "aarch64",
           no_elf_tls))]