diff options
| author | Mathieu David <mathieudavid@mathieudavid.org> | 2015-07-27 20:46:01 +0200 |
|---|---|---|
| committer | Mathieu David <mathieudavid@mathieudavid.org> | 2015-07-27 20:46:01 +0200 |
| commit | f6e9240a99e86d2c799dc29f179dd2870e51f71d (patch) | |
| tree | a7e5ba20745b16949a45a4612b2708e262693a7b /src/libstd/thread | |
| parent | 003c3eaa62981b791f9eb7bcad015baa1e00d98c (diff) | |
| parent | 3351afeecffcc9ebaeb1188a5cde976da8e4a5aa (diff) | |
| download | rust-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.rs | 25 | ||||
| -rw-r--r-- | src/libstd/thread/mod.rs | 85 | ||||
| -rw-r--r-- | src/libstd/thread/scoped_tls.rs | 3 |
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))] |
