diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-05-12 12:48:14 +1200 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-05-12 12:48:14 +1200 |
| commit | e0216fcc42d5f4961d07378a783c87814097015f (patch) | |
| tree | e5f503c129942a2b7c2815b1c8e4db85b5bbcf1b /src/libstd/sys | |
| parent | aa5ca282b20391c6df51fdfa94e0de5672ccfac1 (diff) | |
| parent | 750f2c63f2737305d33288303cdecb7a470a7922 (diff) | |
| download | rust-e0216fcc42d5f4961d07378a783c87814097015f.tar.gz rust-e0216fcc42d5f4961d07378a783c87814097015f.zip | |
Merge branch 'master' into
Diffstat (limited to 'src/libstd/sys')
27 files changed, 164 insertions, 265 deletions
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs deleted file mode 100644 index 34a58f6c83a..00000000000 --- a/src/libstd/sys/common/helper_thread.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementation of the helper thread for the timer module -//! -//! This module contains the management necessary for the timer worker thread. -//! This thread is responsible for performing the send()s on channels for timers -//! that are using channels instead of a blocking call. -//! -//! The timer thread is lazily initialized, and it's shut down via the -//! `shutdown` function provided. It must be maintained as an invariant that -//! `shutdown` is only called when the entire program is finished. No new timers -//! can be created in the future and there must be no active timers at that -//! time. - -use prelude::v1::*; - -use boxed; -use cell::UnsafeCell; -use rt; -use sync::{StaticMutex, StaticCondvar}; -use sync::mpsc::{channel, Sender, Receiver}; -use sys::helper_signal; - -use thread; - -/// A structure for management of a helper thread. -/// -/// This is generally a static structure which tracks the lifetime of a helper -/// thread. -/// -/// The fields of this helper are all public, but they should not be used, this -/// is for static initialization. -pub struct Helper<M:Send> { - /// Internal lock which protects the remaining fields - pub lock: StaticMutex, - pub cond: StaticCondvar, - - // You'll notice that the remaining fields are UnsafeCell<T>, and this is - // because all helper thread operations are done through &self, but we need - // these to be mutable (once `lock` is held). - - /// Lazily allocated channel to send messages to the helper thread. - pub chan: UnsafeCell<*mut Sender<M>>, - - /// OS handle used to wake up a blocked helper thread - pub signal: UnsafeCell<usize>, - - /// Flag if this helper thread has booted and been initialized yet. - pub initialized: UnsafeCell<bool>, - - /// Flag if this helper thread has shut down - pub shutdown: UnsafeCell<bool>, -} - -unsafe impl<M:Send> Send for Helper<M> { } - -unsafe impl<M:Send> Sync for Helper<M> { } - -struct RaceBox(helper_signal::signal); - -unsafe impl Send for RaceBox {} -unsafe impl Sync for RaceBox {} - -macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( - static $name: Helper<$m> = Helper { - lock: ::sync::MUTEX_INIT, - cond: ::sync::CONDVAR_INIT, - chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, - signal: ::cell::UnsafeCell { value: 0 }, - initialized: ::cell::UnsafeCell { value: false }, - shutdown: ::cell::UnsafeCell { value: false }, - }; -) } - -impl<M: Send> Helper<M> { - /// Lazily boots a helper thread, becoming a no-op if the helper has already - /// been spawned. - /// - /// This function will check to see if the thread has been initialized, and - /// if it has it returns quickly. If initialization has not happened yet, - /// the closure `f` will be run (inside of the initialization lock) and - /// passed to the helper thread in a separate task. - /// - /// This function is safe to be called many times. - pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where - T: Send + 'static, - F: FnOnce() -> T, - { - unsafe { - let _guard = self.lock.lock().unwrap(); - if *self.chan.get() as usize == 0 { - let (tx, rx) = channel(); - *self.chan.get() = boxed::into_raw(box tx); - let (receive, send) = helper_signal::new(); - *self.signal.get() = send as usize; - - let receive = RaceBox(receive); - - let t = f(); - thread::spawn(move || { - helper(receive.0, rx, t); - let _g = self.lock.lock().unwrap(); - *self.shutdown.get() = true; - self.cond.notify_one() - }); - - let _ = rt::at_exit(move || { self.shutdown() }); - *self.initialized.get() = true; - } else if *self.chan.get() as usize == 1 { - panic!("cannot continue usage after shutdown"); - } - } - } - - /// Sends a message to a spawned worker thread. - /// - /// This is only valid if the worker thread has previously booted - pub fn send(&'static self, msg: M) { - unsafe { - let _guard = self.lock.lock().unwrap(); - - // Must send and *then* signal to ensure that the child receives the - // message. Otherwise it could wake up and go to sleep before we - // send the message. - assert!(*self.chan.get() as usize != 0); - assert!(*self.chan.get() as usize != 1, - "cannot continue usage after shutdown"); - (**self.chan.get()).send(msg).unwrap(); - helper_signal::signal(*self.signal.get() as helper_signal::signal); - } - } - - fn shutdown(&'static self) { - unsafe { - // Shut down, but make sure this is done inside our lock to ensure - // that we'll always receive the exit signal when the thread - // returns. - let mut guard = self.lock.lock().unwrap(); - - let ptr = *self.chan.get(); - if ptr as usize == 1 { - panic!("cannot continue usage after shutdown"); - } - // Close the channel by destroying it - let chan = Box::from_raw(*self.chan.get()); - *self.chan.get() = 1 as *mut Sender<M>; - drop(chan); - helper_signal::signal(*self.signal.get() as helper_signal::signal); - - // Wait for the child to exit - while !*self.shutdown.get() { - guard = self.cond.wait(guard).unwrap(); - } - drop(guard); - - // Clean up after ourselves - self.lock.destroy(); - helper_signal::close(*self.signal.get() as helper_signal::signal); - *self.signal.get() = 0; - } - } -} diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index 95294b813ea..b528575bbed 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -15,7 +15,7 @@ use prelude::v1::*; pub mod backtrace; pub mod condvar; pub mod mutex; -pub mod net2; +pub mod net; pub mod poison; pub mod remutex; pub mod rwlock; diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net.rs index 2b2c31d92ed..7da7071670a 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net.rs @@ -11,6 +11,7 @@ use prelude::v1::*; use ffi::{CStr, CString}; +use fmt; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; @@ -268,6 +269,24 @@ impl FromInner<Socket> for TcpStream { } } +impl fmt::Debug for TcpStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpStream"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + if let Ok(peer) = self.peer_addr() { + res = res.field("peer", &peer); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -327,6 +346,20 @@ impl FromInner<Socket> for TcpListener { } } +impl fmt::Debug for TcpListener { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpListener"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -445,3 +478,17 @@ impl FromInner<Socket> for UdpSocket { UdpSocket { inner: socket } } } + +impl fmt::Debug for UdpSocket { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("UdpSocket"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs index 6deb4a48007..67679c11a98 100644 --- a/src/libstd/sys/common/poison.rs +++ b/src/libstd/sys/common/poison.rs @@ -10,6 +10,7 @@ use prelude::v1::*; +use marker::Reflect; use cell::UnsafeCell; use error::{Error}; use fmt; @@ -54,7 +55,7 @@ pub struct Guard { /// A type of error which can be returned whenever a lock is acquired. /// -/// Both Mutexes and RwLocks are poisoned whenever a task fails while the lock +/// Both Mutexes and RwLocks are poisoned whenever a thread fails while the lock /// is held. The precise semantics for when a lock is poisoned is documented on /// each lock, but once a lock is poisoned then all future acquisitions will /// return this error. @@ -67,7 +68,7 @@ pub struct PoisonError<T> { /// `try_lock` method. #[stable(feature = "rust1", since = "1.0.0")] pub enum TryLockError<T> { - /// The lock could not be acquired because another task failed while holding + /// The lock could not be acquired because another thread failed while holding /// the lock. #[stable(feature = "rust1", since = "1.0.0")] Poisoned(PoisonError<T>), @@ -109,7 +110,7 @@ impl<T> fmt::Display for PoisonError<T> { } } -impl<T: Send> Error for PoisonError<T> { +impl<T: Send + Reflect> Error for PoisonError<T> { fn description(&self) -> &str { "poisoned lock: another task failed inside" } @@ -155,13 +156,13 @@ impl<T> fmt::Debug for TryLockError<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Send> fmt::Display for TryLockError<T> { +impl<T: Send + Reflect> fmt::Display for TryLockError<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } } -impl<T: Send> Error for TryLockError<T> { +impl<T: Send + Reflect> Error for TryLockError<T> { fn description(&self) -> &str { match *self { TryLockError::Poisoned(ref p) => p.description(), diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs index 48c74b8d89e..1a467580672 100644 --- a/src/libstd/sys/common/remutex.rs +++ b/src/libstd/sys/common/remutex.rs @@ -19,9 +19,9 @@ use sys::mutex as sys; /// A re-entrant mutual exclusion /// -/// This mutex will block *other* threads waiting for the lock to become available. The thread -/// which has already locked the mutex can lock it multiple times without blocking, preventing a -/// common source of deadlocks. +/// This mutex will block *other* threads waiting for the lock to become +/// available. The thread which has already locked the mutex can lock it +/// multiple times without blocking, preventing a common source of deadlocks. pub struct ReentrantMutex<T> { inner: Box<sys::ReentrantMutex>, poison: poison::Flag, @@ -51,10 +51,14 @@ impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {} impl<T> ReentrantMutex<T> { /// Creates a new reentrant mutex in an unlocked state. pub fn new(t: T) -> ReentrantMutex<T> { - ReentrantMutex { - inner: box unsafe { sys::ReentrantMutex::new() }, - poison: poison::FLAG_INIT, - data: t, + unsafe { + let mut mutex = ReentrantMutex { + inner: box sys::ReentrantMutex::uninitialized(), + poison: poison::FLAG_INIT, + data: t, + }; + mutex.inner.init(); + return mutex } } diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index 8dc3407db77..fadeebc8150 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -11,13 +11,13 @@ //! Rust stack-limit management //! //! Currently Rust uses a segmented-stack-like scheme in order to detect stack -//! overflow for rust tasks. In this scheme, the prologue of all functions are +//! overflow for rust threads. In this scheme, the prologue of all functions are //! preceded with a check to see whether the current stack limits are being //! exceeded. //! //! This module provides the functionality necessary in order to manage these //! stack limits (which are stored in platform-specific locations). The -//! functions here are used at the borders of the task lifetime in order to +//! functions here are used at the borders of the thread lifetime in order to //! manage these limits. //! //! This function is an unstable module because this scheme for stack overflow diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 56a952e6a7e..cb9239ed7ba 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -161,7 +161,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: Vec::with_capacity(n) } } - /// Creates a WTF-8 string from an UTF-8 `String`. + /// Creates a WTF-8 string from a UTF-8 `String`. /// /// This takes ownership of the `String` and does not copy. /// @@ -171,7 +171,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: string.into_bytes() } } - /// Creates a WTF-8 string from an UTF-8 `&str` slice. + /// Creates a WTF-8 string from a UTF-8 `&str` slice. /// /// This copies the content of the slice. /// @@ -245,7 +245,7 @@ impl Wtf8Buf { self.bytes.capacity() } - /// Append an UTF-8 slice at the end of the string. + /// Append a UTF-8 slice at the end of the string. #[inline] pub fn push_str(&mut self, other: &str) { self.bytes.push_all(other.as_bytes()) @@ -527,7 +527,7 @@ impl Wtf8 { } /// Lossily converts the string to UTF-8. - /// Returns an UTF-8 `&str` slice if the contents are well-formed in UTF-8. + /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8. /// /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). /// diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index ca805ad0242..135ae1bf916 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -22,7 +22,7 @@ /// getting both accurate backtraces and accurate symbols across platforms. /// This route was not chosen in favor of the next option, however. /// -/// * We're already using libgcc_s for exceptions in rust (triggering task +/// * We're already using libgcc_s for exceptions in rust (triggering thread /// unwinding and running destructors on the stack), and it turns out that it /// conveniently comes with a function that also gives us a backtrace. All of /// these functions look like _Unwind_*, but it's not quite the full @@ -116,7 +116,7 @@ pub fn write(w: &mut Write) -> io::Result<()> { // while it doesn't requires lock for work as everything is // local, it still displays much nicer backtraces when a - // couple of tasks panic simultaneously + // couple of threads panic simultaneously static LOCK: StaticMutex = MUTEX_INIT; let _g = LOCK.lock(); diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 2e4ed38e50f..a6953437497 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -102,7 +102,7 @@ impl OpenOptionsExt for OpenOptions { } #[unstable(feature = "metadata_ext", reason = "recently added API")] -pub struct Metadata(sys::fs2::FileAttr); +pub struct Metadata(sys::fs::FileAttr); #[unstable(feature = "metadata_ext", reason = "recently added API")] pub trait MetadataExt { @@ -111,7 +111,7 @@ pub trait MetadataExt { impl MetadataExt for fs::Metadata { fn as_raw(&self) -> &Metadata { - let inner: &sys::fs2::FileAttr = self.as_inner(); + let inner: &sys::fs::FileAttr = self.as_inner(); unsafe { mem::transmute(inner) } } } @@ -138,11 +138,11 @@ impl Metadata { pub fn rdev(&self) -> raw::dev_t { self.0.raw().st_rdev as raw::dev_t } pub fn size(&self) -> raw::off_t { self.0.raw().st_size as raw::off_t } pub fn atime(&self) -> raw::time_t { self.0.raw().st_atime } - pub fn atime_nsec(&self) -> c_long { self.0.raw().st_atime } + pub fn atime_nsec(&self) -> c_long { self.0.raw().st_atime_nsec as c_long } pub fn mtime(&self) -> raw::time_t { self.0.raw().st_mtime } - pub fn mtime_nsec(&self) -> c_long { self.0.raw().st_mtime } + pub fn mtime_nsec(&self) -> c_long { self.0.raw().st_mtime_nsec as c_long } pub fn ctime(&self) -> raw::time_t { self.0.raw().st_ctime } - pub fn ctime_nsec(&self) -> c_long { self.0.raw().st_ctime } + pub fn ctime_nsec(&self) -> c_long { self.0.raw().st_ctime_nsec as c_long } pub fn blksize(&self) -> raw::blksize_t { self.0.raw().st_blksize as raw::blksize_t @@ -187,7 +187,7 @@ impl DirEntryExt for fs::DirEntry { #[stable(feature = "rust1", since = "1.0.0")] pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { - sys::fs2::symlink(src.as_ref(), dst.as_ref()) + sys::fs::symlink(src.as_ref(), dst.as_ref()) } #[unstable(feature = "dir_builder", reason = "recently added API")] diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs index 8cb4b4907f6..79e59ddab5b 100644 --- a/src/libstd/sys/unix/ext/io.rs +++ b/src/libstd/sys/unix/ext/io.rs @@ -16,7 +16,7 @@ use fs; use net; use os::raw; use sys; -use sys_common::{net2, AsInner, FromInner}; +use sys_common::{self, AsInner, FromInner}; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] @@ -41,8 +41,7 @@ pub trait AsRawFd { /// A trait to express the ability to construct an object from a raw file /// descriptor. -#[unstable(feature = "from_raw_os", - reason = "recent addition to std::os::unix::io")] +#[stable(feature = "from_raw_os", since = "1.1.0")] pub trait FromRawFd { /// Constructs a new instances of `Self` from the given raw file /// descriptor. @@ -56,6 +55,7 @@ pub trait FromRawFd { /// descriptor they are wrapping. Usage of this function could /// accidentally allow violating this contract which can cause memory /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_fd(fd: RawFd) -> Self; } @@ -65,10 +65,10 @@ impl AsRawFd for fs::File { self.as_inner().fd().raw() } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for fs::File { unsafe fn from_raw_fd(fd: RawFd) -> fs::File { - fs::File::from_inner(sys::fs2::File::from_inner(fd)) + fs::File::from_inner(sys::fs::File::from_inner(fd)) } } @@ -85,24 +85,24 @@ impl AsRawFd for net::UdpSocket { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { let socket = sys::net::Socket::from_inner(fd); - net::TcpStream::from_inner(net2::TcpStream::from_inner(socket)) + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpListener { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { let socket = sys::net::Socket::from_inner(fd); - net::TcpListener::from_inner(net2::TcpListener::from_inner(socket)) + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::UdpSocket { unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { let socket = sys::net::Socket::from_inner(fd); - net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket)) + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) } } diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 8c9d0a86583..45d0d62a015 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -58,7 +58,7 @@ pub trait ExitStatusExt { impl ExitStatusExt for process::ExitStatus { fn signal(&self) -> Option<i32> { match *self.as_inner() { - sys::process2::ExitStatus::Signal(s) => Some(s), + sys::process::ExitStatus::Signal(s) => Some(s), _ => None } } diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index e5bdb554359..026380027d2 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -31,7 +31,7 @@ impl FileDesc { /// Extracts the actual filedescriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; - unsafe { mem::forget(self) }; + mem::forget(self); fd } diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs.rs index 350161c751c..350161c751c 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs.rs diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 78b798d3bff..c1a4e8cee9e 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -33,13 +33,13 @@ pub mod c; pub mod condvar; pub mod ext; pub mod fd; -pub mod fs2; +pub mod fs; pub mod mutex; pub mod net; pub mod os; pub mod os_str; -pub mod pipe2; -pub mod process2; +pub mod pipe; +pub mod process; pub mod rwlock; pub mod stack_overflow; pub mod sync; diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index af814653c14..70d14f63dbc 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -69,30 +69,27 @@ impl Mutex { } } -// FIXME: remove the box, because box happens twice now, once at the common layer and once here. -// Box is necessary here, because mutex may not change address after it is intialised on some -// platforms. Regular Mutex above handles this by offloading intialisation to the OS on first lock. -// Sadly, as far as reentrant mutexes go, this scheme is not quite portable and we must initialise -// when we create the mutex, in the `new`. -pub struct ReentrantMutex { inner: Box<UnsafeCell<ffi::pthread_mutex_t>> } +pub struct ReentrantMutex { inner: UnsafeCell<ffi::pthread_mutex_t> } unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn new() -> ReentrantMutex { - let mutex = ReentrantMutex { inner: box mem::uninitialized() }; + pub unsafe fn uninitialized() -> ReentrantMutex { + ReentrantMutex { inner: mem::uninitialized() } + } + + pub unsafe fn init(&mut self) { let mut attr: ffi::pthread_mutexattr_t = mem::uninitialized(); let result = ffi::pthread_mutexattr_init(&mut attr as *mut _); debug_assert_eq!(result, 0); let result = ffi::pthread_mutexattr_settype(&mut attr as *mut _, ffi::PTHREAD_MUTEX_RECURSIVE); debug_assert_eq!(result, 0); - let result = ffi::pthread_mutex_init(mutex.inner.get(), &attr as *const _); + let result = ffi::pthread_mutex_init(self.inner.get(), &attr as *const _); debug_assert_eq!(result, 0); let result = ffi::pthread_mutexattr_destroy(&mut attr as *mut _); debug_assert_eq!(result, 0); - mutex } pub unsafe fn lock(&self) { diff --git a/src/libstd/sys/unix/pipe2.rs b/src/libstd/sys/unix/pipe.rs index e9d8c69fefb..e9d8c69fefb 100644 --- a/src/libstd/sys/unix/pipe2.rs +++ b/src/libstd/sys/unix/pipe.rs diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process.rs index 4e7c4d241f5..290310f4ad9 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process.rs @@ -18,9 +18,9 @@ use fmt; use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_void, c_int, gid_t, uid_t}; use ptr; -use sys::pipe2::AnonPipe; +use sys::pipe::AnonPipe; use sys::{self, c, cvt, cvt_r}; -use sys::fs2::{File, OpenOptions}; +use sys::fs::{File, OpenOptions}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -141,7 +141,7 @@ impl Process { let (envp, _a, _b) = make_envp(cfg.env.as_ref()); let (argv, _a) = make_argv(&cfg.program, &cfg.args); - let (input, output) = try!(sys::pipe2::anon_pipe()); + let (input, output) = try!(sys::pipe::anon_pipe()); let pid = unsafe { match libc::fork() { @@ -328,7 +328,7 @@ impl Process { }) { Ok(0) => None, Ok(n) if n == self.pid => Some(translate_status(status)), - Ok(n) => panic!("unkown pid: {}", n), + Ok(n) => panic!("unknown pid: {}", n), Err(e) => panic!("unknown waitpid error: {}", e), } } diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index adf9da2d067..7bb9fb68c14 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -10,6 +10,7 @@ use prelude::v1::*; +use libc; use cell::UnsafeCell; use sys::sync as ffi; @@ -26,7 +27,23 @@ impl RWLock { #[inline] pub unsafe fn read(&self) { let r = ffi::pthread_rwlock_rdlock(self.inner.get()); - debug_assert_eq!(r, 0); + + // According to the pthread_rwlock_rdlock spec, this function **may** + // fail with EDEADLK if a deadlock is detected. On the other hand + // pthread mutexes will *never* return EDEADLK if they are initialized + // as the "fast" kind (which ours always are). As a result, a deadlock + // situation may actually return from the call to pthread_rwlock_rdlock + // instead of blocking forever (as mutexes and Windows rwlocks do). Note + // that not all unix implementations, however, will return EDEADLK for + // their rwlocks. + // + // We roughly maintain the deadlocking behavior by panicking to ensure + // that this lock acquisition does not succeed. + if r == libc::EDEADLK { + panic!("rwlock read lock would result in deadlock"); + } else { + debug_assert_eq!(r, 0); + } } #[inline] pub unsafe fn try_read(&self) -> bool { @@ -35,7 +52,12 @@ impl RWLock { #[inline] pub unsafe fn write(&self) { let r = ffi::pthread_rwlock_wrlock(self.inner.get()); - debug_assert_eq!(r, 0); + // see comments above for why we check for EDEADLK + if r == libc::EDEADLK { + panic!("rwlock write lock would result in deadlock"); + } else { + debug_assert_eq!(r, 0); + } } #[inline] pub unsafe fn try_write(&self) -> bool { @@ -49,21 +71,16 @@ impl RWLock { #[inline] pub unsafe fn write_unlock(&self) { self.read_unlock() } #[inline] - #[cfg(not(target_os = "dragonfly"))] - pub unsafe fn destroy(&self) { - let r = ffi::pthread_rwlock_destroy(self.inner.get()); - debug_assert_eq!(r, 0); - } - - #[inline] - #[cfg(target_os = "dragonfly")] pub unsafe fn destroy(&self) { - use libc; let r = ffi::pthread_rwlock_destroy(self.inner.get()); // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a // rwlock that was just initialized with // ffi::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked) // or pthread_rwlock_init() is called, this behaviour no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); + if cfg!(target_os = "dragonfly") { + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } } } diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 23c1fcf4b3c..822e1b370c2 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -125,7 +125,7 @@ impl MetadataExt for Metadata { #[stable(feature = "rust1", since = "1.0.0")] pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { - sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false) + sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false) } /// Creates a new directory symlink on the filesystem. @@ -146,5 +146,5 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) #[stable(feature = "rust1", since = "1.0.0")] pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { - sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true) + sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true) } diff --git a/src/libstd/sys/windows/ext/io.rs b/src/libstd/sys/windows/ext/io.rs index b88a6316eee..f4717eb2425 100644 --- a/src/libstd/sys/windows/ext/io.rs +++ b/src/libstd/sys/windows/ext/io.rs @@ -13,7 +13,7 @@ use fs; use os::windows::raw; use net; -use sys_common::{net2, AsInner, FromInner}; +use sys_common::{self, AsInner, FromInner}; use sys; /// Raw HANDLEs. @@ -33,8 +33,7 @@ pub trait AsRawHandle { } /// Construct I/O objects from raw handles. -#[unstable(feature = "from_raw_os", - reason = "recent addition to the std::os::windows::io module")] +#[stable(feature = "from_raw_os", since = "1.1.0")] pub trait FromRawHandle { /// Constructs a new I/O object from the specified raw handle. /// @@ -47,6 +46,7 @@ pub trait FromRawHandle { /// descriptor they are wrapping. Usage of this function could /// accidentally allow violating this contract which can cause memory /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_handle(handle: RawHandle) -> Self; } @@ -57,11 +57,11 @@ impl AsRawHandle for fs::File { } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { let handle = handle as ::libc::HANDLE; - fs::File::from_inner(sys::fs2::File::from_inner(handle)) + fs::File::from_inner(sys::fs::File::from_inner(handle)) } } @@ -74,7 +74,7 @@ pub trait AsRawSocket { } /// Create I/O objects from raw sockets. -#[unstable(feature = "from_raw_os", reason = "recent addition to module")] +#[stable(feature = "from_raw_os", since = "1.1.0")] pub trait FromRawSocket { /// Creates a new I/O object from the given raw socket. /// @@ -86,6 +86,7 @@ pub trait FromRawSocket { /// descriptor they are wrapping. Usage of this function could /// accidentally allow violating this contract which can cause memory /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_socket(sock: RawSocket) -> Self; } @@ -108,24 +109,24 @@ impl AsRawSocket for net::UdpSocket { } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpStream { unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { let sock = sys::net::Socket::from_inner(sock); - net::TcpStream::from_inner(net2::TcpStream::from_inner(sock)) + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpListener { unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { let sock = sys::net::Socket::from_inner(sock); - net::TcpListener::from_inner(net2::TcpListener::from_inner(sock)) + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) } } -#[unstable(feature = "from_raw_os", reason = "trait is unstable")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::UdpSocket { unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { let sock = sys::net::Socket::from_inner(sock); - net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock)) + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) } } diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs.rs index 03a56e2958a..03a56e2958a 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs.rs diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 9481e180ce5..c835d503388 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -32,7 +32,7 @@ impl Handle { pub fn into_raw(self) -> HANDLE { let ret = self.0; - unsafe { mem::forget(self) } + mem::forget(self); return ret; } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 5ae5f6f201b..4c30f0f8660 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -25,14 +25,14 @@ pub mod backtrace; pub mod c; pub mod condvar; pub mod ext; -pub mod fs2; +pub mod fs; pub mod handle; pub mod mutex; pub mod net; pub mod os; pub mod os_str; -pub mod pipe2; -pub mod process2; +pub mod pipe; +pub mod process; pub mod rwlock; pub mod stack_overflow; pub mod sync; diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index ca20858bb5b..9d2624f9418 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -59,16 +59,18 @@ impl Mutex { } } -pub struct ReentrantMutex { inner: Box<UnsafeCell<ffi::CRITICAL_SECTION>> } +pub struct ReentrantMutex { inner: UnsafeCell<ffi::CRITICAL_SECTION> } unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn new() -> ReentrantMutex { - let mutex = ReentrantMutex { inner: box mem::uninitialized() }; - ffi::InitializeCriticalSection(mutex.inner.get()); - mutex + pub unsafe fn uninitialized() -> ReentrantMutex { + mem::uninitialized() + } + + pub unsafe fn init(&mut self) { + ffi::InitializeCriticalSection(self.inner.get()); } pub unsafe fn lock(&self) { diff --git a/src/libstd/sys/windows/pipe2.rs b/src/libstd/sys/windows/pipe.rs index b441d8beedb..b441d8beedb 100644 --- a/src/libstd/sys/windows/pipe2.rs +++ b/src/libstd/sys/windows/pipe.rs diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process.rs index 5aad5f668dd..032a349b00e 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process.rs @@ -26,9 +26,9 @@ use path::Path; use ptr; use sync::{StaticMutex, MUTEX_INIT}; use sys::c; -use sys::fs2::{OpenOptions, File}; +use sys::fs::{OpenOptions, File}; use sys::handle::Handle; -use sys::pipe2::AnonPipe; +use sys::pipe::AnonPipe; use sys::stdio; use sys::{self, cvt}; use sys_common::{AsInner, FromInner}; diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index cbabab8acb7..ea5af3f2830 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -32,7 +32,7 @@ pub type Dtor = unsafe extern fn(*mut u8); // somewhere to run arbitrary code on thread termination. With this in place // we'll be able to run anything we like, including all TLS destructors! // -// To accomplish this feat, we perform a number of tasks, all contained +// To accomplish this feat, we perform a number of threads, all contained // within this module: // // * All TLS destructors are tracked by *us*, not the windows runtime. This |
