Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Nikolai Vazquez
2017-09-30 10:08:33 -04:00
362 changed files with 7972 additions and 4180 deletions

View File

@@ -36,7 +36,7 @@ rustc_tsan = { path = "../librustc_tsan" }
[build-dependencies]
build_helper = { path = "../build_helper" }
gcc = "0.3.50"
cc = "1.0"
[features]
backtrace = []

View File

@@ -11,7 +11,7 @@
#![deny(warnings)]
extern crate build_helper;
extern crate gcc;
extern crate cc;
use std::env;
use std::process::Command;
@@ -68,8 +68,8 @@ fn main() {
if cfg!(feature = "backtrace") {
println!("cargo:rustc-link-lib=backtrace");
}
println!("cargo:rustc-link-lib=magenta");
println!("cargo:rustc-link-lib=mxio");
println!("cargo:rustc-link-lib=zircon");
println!("cargo:rustc-link-lib=fdio");
println!("cargo:rustc-link-lib=launchpad"); // for std::process
}
}
@@ -77,7 +77,7 @@ fn main() {
fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
let compiler = gcc::Build::new().get_compiler();
let compiler = cc::Build::new().get_compiler();
// only msvc returns None for ar so unwrap is okay
let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())

View File

@@ -691,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S>
/// Returns a reference to the map's [`BuildHasher`].
///
/// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let hasher = RandomState::new();
/// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
/// let hasher: &RandomState = map.hasher();
/// ```
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
pub fn hasher(&self) -> &S {
&self.hash_builder
@@ -2191,6 +2202,36 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
fn take_key(&mut self) -> Option<K> {
self.key.take()
}
/// Replaces the entry, returning the old key and value.
///
/// # Examples
///
/// ```
/// #![feature(map_entry_replace)]
/// use std::collections::HashMap;
/// use std::collections::hash_map::Entry;
///
/// let mut map: HashMap<String, u32> = HashMap::new();
/// map.insert("poneyland".to_string(), 15);
///
/// if let Entry::Occupied(entry) = map.entry("poneyland".to_string()) {
/// let (old_key, old_value): (String, u32) = entry.replace(16);
/// assert_eq!(old_key, "poneyland");
/// assert_eq!(old_value, 15);
/// }
///
/// assert_eq!(map.get("poneyland"), Some(&16));
/// ```
#[unstable(feature = "map_entry_replace", issue = "44286")]
pub fn replace(mut self, value: V) -> (K, V) {
let (old_key, old_value) = self.elem.read_mut();
let old_key = mem::replace(old_key, self.key.unwrap());
let old_value = mem::replace(old_value, value);
(old_key, old_value)
}
}
impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {

View File

@@ -56,6 +56,7 @@ use any::TypeId;
use borrow::Cow;
use cell;
use char;
use convert;
use core::array;
use fmt::{self, Debug, Display};
use mem::transmute;
@@ -370,6 +371,13 @@ impl Error for char::ParseCharError {
}
}
#[unstable(feature = "try_from", issue = "33417")]
impl Error for convert::Infallible {
fn description(&self) -> &str {
match *self {
}
}
}
// copied from any.rs
impl Error + 'static {

View File

@@ -1595,9 +1595,9 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// Notable exception is made for situations where any of the directories
/// specified in the `path` could not be created as it was being created concurrently.
/// Such cases are considered success. In other words: calling `create_dir_all`
/// concurrently from multiple threads or processes is guaranteed to not fail
/// due to race itself.
/// Such cases are considered to be successful. That is, calling `create_dir_all`
/// concurrently from multiple threads or processes is guaranteed not to fail
/// due to a race condition with itself.
///
/// # Examples
///
@@ -2160,6 +2160,27 @@ mod tests {
check!(fs::remove_file(&filename));
}
#[test]
#[cfg(unix)]
fn set_get_unix_permissions() {
use os::unix::fs::PermissionsExt;
let tmpdir = tmpdir();
let filename = &tmpdir.join("set_get_unix_permissions");
check!(fs::create_dir(filename));
let mask = 0o7777;
check!(fs::set_permissions(filename,
fs::Permissions::from_mode(0)));
let metadata0 = check!(fs::metadata(filename));
assert_eq!(mask & metadata0.permissions().mode(), 0);
check!(fs::set_permissions(filename,
fs::Permissions::from_mode(0o1777)));
let metadata1 = check!(fs::metadata(filename));
assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
}
#[test]
#[cfg(windows)]
fn file_test_io_seek_read_write() {

View File

@@ -40,9 +40,10 @@ use mem;
///
/// io::copy(&mut reader, &mut writer)?;
///
/// assert_eq!(reader, &writer[..]);
/// assert_eq!(&b"hello"[..], &writer[..]);
/// # Ok(())
/// # }
/// # foo().unwrap();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>

View File

@@ -167,7 +167,7 @@ impl TcpStream {
/// connection request.
///
/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
#[stable(feature = "tcpstream_connect_timeout", since = "1.22.0")]
#[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
}

View File

@@ -710,6 +710,10 @@ mod prim_u128 { }
//
/// The pointer-sized signed integer type.
///
/// The size of this primitive is how many bytes it takes to reference any
/// location in memory. For example, on a 32 bit target, this is 4 bytes
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::isize` module](isize/index.html).*
///
/// However, please note that examples are shared between primitive integer
@@ -722,6 +726,10 @@ mod prim_isize { }
//
/// The pointer-sized unsigned integer type.
///
/// The size of this primitive is how many bytes it takes to reference any
/// location in memory. For example, on a 32 bit target, this is 4 bytes
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::usize` module](usize/index.html).*
///
/// However, please note that examples are shared between primitive integer

View File

@@ -106,15 +106,18 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
pub struct Child {
handle: imp::Process,
/// The handle for writing to the child's stdin, if it has been captured
/// The handle for writing to the child's standard input (stdin), if it has
/// been captured.
#[stable(feature = "process", since = "1.0.0")]
pub stdin: Option<ChildStdin>,
/// The handle for reading from the child's stdout, if it has been captured
/// The handle for reading from the child's standard output (stdout), if it
/// has been captured.
#[stable(feature = "process", since = "1.0.0")]
pub stdout: Option<ChildStdout>,
/// The handle for reading from the child's stderr, if it has been captured
/// The handle for reading from the child's standard error (stderr), if it
/// has been captured.
#[stable(feature = "process", since = "1.0.0")]
pub stderr: Option<ChildStderr>,
}
@@ -149,12 +152,17 @@ impl fmt::Debug for Child {
}
}
/// A handle to a child process's stdin.
/// A handle to a child process's standard input (stdin).
///
/// This struct is used in the [`stdin`] field on [`Child`].
///
/// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying
/// file handle will be closed. If the child process was blocked on input prior
/// to being dropped, it will become unblocked after dropping.
///
/// [`Child`]: struct.Child.html
/// [`stdin`]: struct.Child.html#structfield.stdin
/// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin {
inner: AnonPipe
@@ -192,12 +200,16 @@ impl fmt::Debug for ChildStdin {
}
}
/// A handle to a child process's stdout.
/// A handle to a child process's standard output (stdout).
///
/// This struct is used in the [`stdout`] field on [`Child`].
///
/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
/// underlying file handle will be closed.
///
/// [`Child`]: struct.Child.html
/// [`stdout`]: struct.Child.html#structfield.stdout
/// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout {
inner: AnonPipe
@@ -239,8 +251,12 @@ impl fmt::Debug for ChildStdout {
///
/// This struct is used in the [`stderr`] field on [`Child`].
///
/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
/// underlying file handle will be closed.
///
/// [`Child`]: struct.Child.html
/// [`stderr`]: struct.Child.html#structfield.stderr
/// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr {
inner: AnonPipe
@@ -534,7 +550,7 @@ impl Command {
self
}
/// Configuration for the child process's stdin handle (file descriptor 0).
/// Configuration for the child process's standard input (stdin) handle.
///
/// # Examples
///
@@ -554,7 +570,7 @@ impl Command {
self
}
/// Configuration for the child process's stdout handle (file descriptor 1).
/// Configuration for the child process's standard output (stdout) handle.
///
/// # Examples
///
@@ -574,7 +590,7 @@ impl Command {
self
}
/// Configuration for the child process's stderr handle (file descriptor 2).
/// Configuration for the child process's standard error (stderr) handle.
///
/// # Examples
///

View File

@@ -24,19 +24,24 @@ use sys_common::rwlock as sys;
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that aquire the lock, therefore blocking any threads waiting for the lock to
/// become available. An `RwLock` will allow any number of readers to aquire the
/// lock as long as a writer is not holding the lock.
///
/// The priority policy of the lock is dependent on the underlying operating
/// system's implementation, and this type does not guarantee that any
/// particular policy will be used.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
/// allow concurrent access through readers. The RAII guards returned from the
/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
/// to allow access to the contained of the lock.
/// required that `T` satisfies [`Send`] to be shared across threads and
/// [`Sync`] to allow concurrent access through readers. The RAII guards
/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
/// for the `write` methods) to allow access to the contained of the lock.
///
/// # Poisoning
///
/// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however,
/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however,
/// that an `RwLock` may only be poisoned if a panic occurs while it is locked
/// exclusively (write mode). If a panic occurs in any reader, then the lock
/// will not be poisoned.
@@ -63,6 +68,12 @@ use sys_common::rwlock as sys;
/// assert_eq!(*w, 6);
/// } // write lock is dropped here
/// ```
///
/// [`Deref`]: ../../std/ops/trait.Deref.html
/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
/// [`Send`]: ../../std/marker/trait.Send.html
/// [`Sync`]: ../../std/marker/trait.Sync.html
/// [`Mutex`]: struct.Mutex.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLock<T: ?Sized> {
inner: Box<sys::RWLock>,
@@ -154,6 +165,24 @@ impl<T: ?Sized> RwLock<T> {
/// # Panics
///
/// This function might panic when called if the lock is already held by the current thread.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, RwLock};
/// use std::thread;
///
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// thread::spawn(move || {
/// let r = c_lock.read();
/// assert!(r.is_ok());
/// }).join().unwrap();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@@ -180,6 +209,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// match lock.try_read() {
/// Ok(n) => assert_eq!(*n, 1),
/// Err(_) => unreachable!(),
/// };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
@@ -210,6 +252,19 @@ impl<T: ?Sized> RwLock<T> {
/// # Panics
///
/// This function might panic when called if the lock is already held by the current thread.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let mut n = lock.write().unwrap();
/// *n = 2;
///
/// assert!(lock.try_read().is_err());
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
@@ -236,6 +291,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// assert!(lock.try_write().is_err());
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
@@ -253,6 +321,22 @@ impl<T: ?Sized> RwLock<T> {
/// If another thread is active, the lock can still become poisoned at any
/// time. You should not trust a `false` value for program correctness
/// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, RwLock};
/// use std::thread;
///
/// let lock = Arc::new(RwLock::new(0));
/// let c_lock = lock.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_lock.write().unwrap();
/// panic!(); // the lock gets poisoned
/// }).join();
/// assert_eq!(lock.is_poisoned(), true);
/// ```
#[inline]
#[stable(feature = "sync_poison", since = "1.2.0")]
pub fn is_poisoned(&self) -> bool {
@@ -267,6 +351,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(String::new());
/// {
/// let mut s = lock.write().unwrap();
/// *s = "modified".to_owned();
/// }
/// assert_eq!(lock.into_inner().unwrap(), "modified");
/// ```
#[stable(feature = "rwlock_into_inner", since = "1.6.0")]
pub fn into_inner(self) -> LockResult<T> where T: Sized {
// We know statically that there are no outstanding references to
@@ -282,7 +379,7 @@ impl<T: ?Sized> RwLock<T> {
(ptr::read(inner), ptr::read(poison), ptr::read(data))
};
mem::forget(self);
inner.destroy(); // Keep in sync with the `Drop` impl.
inner.destroy(); // Keep in sync with the `Drop` impl.
drop(inner);
poison::map_result(poison.borrow(), |_| data.into_inner())
@@ -300,6 +397,16 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let mut lock = RwLock::new(0);
/// *lock.get_mut().unwrap() = 10;
/// assert_eq!(*lock.read().unwrap(), 10);
/// ```
#[stable(feature = "rwlock_get_mut", since = "1.6.0")]
pub fn get_mut(&mut self) -> LockResult<&mut T> {
// We know statically that there are no other references to `self`, so
@@ -486,7 +593,7 @@ mod tests {
fn test_rw_arc_poison_wr() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
let _: Result<(), _> = thread::spawn(move|| {
let _: Result<(), _> = thread::spawn(move || {
let _lock = arc2.write().unwrap();
panic!();
}).join();
@@ -498,7 +605,7 @@ mod tests {
let arc = Arc::new(RwLock::new(1));
assert!(!arc.is_poisoned());
let arc2 = arc.clone();
let _: Result<(), _> = thread::spawn(move|| {
let _: Result<(), _> = thread::spawn(move || {
let _lock = arc2.write().unwrap();
panic!();
}).join();
@@ -510,7 +617,7 @@ mod tests {
fn test_rw_arc_no_poison_rr() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
let _: Result<(), _> = thread::spawn(move|| {
let _: Result<(), _> = thread::spawn(move || {
let _lock = arc2.read().unwrap();
panic!();
}).join();
@@ -521,7 +628,7 @@ mod tests {
fn test_rw_arc_no_poison_rw() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
let _: Result<(), _> = thread::spawn(move|| {
let _: Result<(), _> = thread::spawn(move || {
let _lock = arc2.read().unwrap();
panic!()
}).join();
@@ -535,7 +642,7 @@ mod tests {
let arc2 = arc.clone();
let (tx, rx) = channel();
thread::spawn(move|| {
thread::spawn(move || {
let mut lock = arc2.write().unwrap();
for _ in 0..10 {
let tmp = *lock;
@@ -550,7 +657,7 @@ mod tests {
let mut children = Vec::new();
for _ in 0..5 {
let arc3 = arc.clone();
children.push(thread::spawn(move|| {
children.push(thread::spawn(move || {
let lock = arc3.read().unwrap();
assert!(*lock >= 0);
}));
@@ -571,7 +678,7 @@ mod tests {
fn test_rw_arc_access_in_unwind() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
let _ = thread::spawn(move|| -> () {
let _ = thread::spawn(move || -> () {
struct Unwinder {
i: Arc<RwLock<isize>>,
}

View File

@@ -68,8 +68,8 @@ impl FileExt for fs::File {
/// Unix-specific extensions to `Permissions`
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait PermissionsExt {
/// Returns the underlying raw `mode_t` bits that are the standard Unix
/// permissions for this file.
/// Returns the underlying raw `st_mode` bits that contain the standard
/// Unix permissions for this file.
///
/// # Examples
///

View File

@@ -95,7 +95,7 @@ pub struct DirBuilder { mode: mode_t }
impl FileAttr {
pub fn size(&self) -> u64 { self.stat.st_size as u64 }
pub fn perm(&self) -> FilePermissions {
FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
FilePermissions { mode: (self.stat.st_mode as mode_t) }
}
pub fn file_type(&self) -> FileType {

View File

@@ -19,4 +19,4 @@ mod process_inner;
#[path = "process_fuchsia.rs"]
mod process_inner;
#[cfg(target_os = "fuchsia")]
mod magenta;
mod zircon;

View File

@@ -13,7 +13,7 @@ use libc;
use mem;
use ptr;
use sys::process::magenta::{Handle, mx_handle_t};
use sys::process::zircon::{Handle, zx_handle_t};
use sys::process::process_common::*;
////////////////////////////////////////////////////////////////////////////////
@@ -51,10 +51,10 @@ impl Command {
}
unsafe fn do_exec(&mut self, stdio: ChildPipes)
-> io::Result<mx_handle_t> {
use sys::process::magenta::*;
-> io::Result<zx_handle_t> {
use sys::process::zircon::*;
let job_handle = mx_job_default();
let job_handle = zx_job_default();
let envp = match *self.get_envp() {
Some(ref envp) => envp.as_ptr(),
None => ptr::null(),
@@ -67,39 +67,39 @@ impl Command {
}
// Duplicate the job handle
let mut job_copy: mx_handle_t = MX_HANDLE_INVALID;
mx_cvt(mx_handle_duplicate(job_handle, MX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
let mut job_copy: zx_handle_t = ZX_HANDLE_INVALID;
zx_cvt(zx_handle_duplicate(job_handle, ZX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
// Create a launchpad
let mut launchpad: *mut launchpad_t = ptr::null_mut();
mx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
zx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
let launchpad_destructor = LaunchpadDestructor(launchpad);
// Set the process argv
mx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1,
zx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1,
self.get_argv().as_ptr()))?;
// Setup the environment vars
mx_cvt(launchpad_set_environ(launchpad, envp))?;
mx_cvt(launchpad_add_vdso_vmo(launchpad))?;
zx_cvt(launchpad_set_environ(launchpad, envp))?;
zx_cvt(launchpad_add_vdso_vmo(launchpad))?;
// Load the executable
mx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?;
mx_cvt(launchpad_load_vdso(launchpad, MX_HANDLE_INVALID))?;
mx_cvt(launchpad_clone(launchpad, LP_CLONE_MXIO_ROOT | LP_CLONE_MXIO_CWD))?;
zx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?;
zx_cvt(launchpad_load_vdso(launchpad, ZX_HANDLE_INVALID))?;
zx_cvt(launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_CWD))?;
// Clone stdin, stdout, and stderr
if let Some(fd) = stdio.stdin.fd() {
mx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
zx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
} else {
mx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
zx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
}
if let Some(fd) = stdio.stdout.fd() {
mx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
zx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
} else {
mx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
zx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
}
if let Some(fd) = stdio.stderr.fd() {
mx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
zx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
} else {
mx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
zx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
}
// We don't want FileDesc::drop to be called on any stdio. It would close their fds. The
@@ -113,9 +113,9 @@ impl Command {
// `launchpad_go` destroys the launchpad, so we must not
mem::forget(launchpad_destructor);
let mut process_handle: mx_handle_t = 0;
let mut process_handle: zx_handle_t = 0;
let mut err_msg: *const libc::c_char = ptr::null();
mx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?;
zx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?;
// FIXME: See if we want to do something with that err_msg
Ok(process_handle)
@@ -136,27 +136,27 @@ impl Process {
}
pub fn kill(&mut self) -> io::Result<()> {
use sys::process::magenta::*;
use sys::process::zircon::*;
unsafe { mx_cvt(mx_task_kill(self.handle.raw()))?; }
unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; }
Ok(())
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
use default::Default;
use sys::process::magenta::*;
use sys::process::zircon::*;
let mut proc_info: mx_info_process_t = Default::default();
let mut actual: mx_size_t = 0;
let mut avail: mx_size_t = 0;
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: zx_size_t = 0;
let mut avail: zx_size_t = 0;
unsafe {
mx_cvt(mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
MX_TIME_INFINITE, ptr::null_mut()))?;
mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
zx_cvt(zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
ZX_TIME_INFINITE, ptr::null_mut()))?;
zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS,
&mut proc_info as *mut _ as *mut libc::c_void,
mem::size_of::<mx_info_process_t>(), &mut actual,
mem::size_of::<zx_info_process_t>(), &mut actual,
&mut avail))?;
}
if actual != 1 {
@@ -168,14 +168,14 @@ impl Process {
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
use default::Default;
use sys::process::magenta::*;
use sys::process::zircon::*;
let mut proc_info: mx_info_process_t = Default::default();
let mut actual: mx_size_t = 0;
let mut avail: mx_size_t = 0;
let mut proc_info: zx_info_process_t = Default::default();
let mut actual: zx_size_t = 0;
let mut avail: zx_size_t = 0;
unsafe {
let status = mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
let status = zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
0, ptr::null_mut());
match status {
0 => { }, // Success
@@ -184,9 +184,9 @@ impl Process {
},
_ => { panic!("Failed to wait on process handle: {}", status); },
}
mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS,
&mut proc_info as *mut _ as *mut libc::c_void,
mem::size_of::<mx_info_process_t>(), &mut actual,
mem::size_of::<zx_info_process_t>(), &mut actual,
&mut avail))?;
}
if actual != 1 {

View File

@@ -17,31 +17,31 @@ use u64;
use libc::{c_int, c_void};
pub type mx_handle_t = i32;
pub type mx_vaddr_t = usize;
pub type mx_rights_t = u32;
pub type mx_status_t = i32;
pub type zx_handle_t = i32;
pub type zx_vaddr_t = usize;
pub type zx_rights_t = u32;
pub type zx_status_t = i32;
pub type mx_size_t = usize;
pub type zx_size_t = usize;
pub const MX_HANDLE_INVALID: mx_handle_t = 0;
pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
pub type mx_time_t = u64;
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;
pub type zx_time_t = u64;
pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX;
pub type mx_signals_t = u32;
pub type zx_signals_t = u32;
pub const MX_OBJECT_SIGNAL_3 : mx_signals_t = 1 << 3;
pub const ZX_OBJECT_SIGNAL_3 : zx_signals_t = 1 << 3;
pub const MX_TASK_TERMINATED : mx_signals_t = MX_OBJECT_SIGNAL_3;
pub const ZX_TASK_TERMINATED : zx_signals_t = ZX_OBJECT_SIGNAL_3;
pub const MX_RIGHT_SAME_RIGHTS : mx_rights_t = 1 << 31;
pub const ZX_RIGHT_SAME_RIGHTS : zx_rights_t = 1 << 31;
pub type mx_object_info_topic_t = u32;
pub type zx_object_info_topic_t = u32;
pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3;
pub const ZX_INFO_PROCESS : zx_object_info_topic_t = 3;
pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
pub fn zx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<zx_status_t>+Copy {
if let Ok(status) = TryInto::try_into(t) {
if status < 0 {
Err(io::Error::from_raw_os_error(status))
@@ -53,33 +53,33 @@ pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
}
}
// Safe wrapper around mx_handle_t
// Safe wrapper around zx_handle_t
pub struct Handle {
raw: mx_handle_t,
raw: zx_handle_t,
}
impl Handle {
pub fn new(raw: mx_handle_t) -> Handle {
pub fn new(raw: zx_handle_t) -> Handle {
Handle {
raw,
}
}
pub fn raw(&self) -> mx_handle_t {
pub fn raw(&self) -> zx_handle_t {
self.raw
}
}
impl Drop for Handle {
fn drop(&mut self) {
unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
unsafe { zx_cvt(zx_handle_close(self.raw)).expect("Failed to close zx_handle_t"); }
}
}
// Common MX_INFO header
// Common ZX_INFO header
#[derive(Default)]
#[repr(C)]
pub struct mx_info_header_t {
pub struct zx_info_header_t {
pub topic: u32, // identifies the info struct
pub avail_topic_size: u16, // “native” size of the struct
pub topic_size: u16, // size of the returned struct (<=topic_size)
@@ -89,34 +89,34 @@ pub struct mx_info_header_t {
#[derive(Default)]
#[repr(C)]
pub struct mx_record_process_t {
pub struct zx_record_process_t {
pub return_code: c_int,
}
// Returned for topic MX_INFO_PROCESS
// Returned for topic ZX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
pub struct mx_info_process_t {
pub hdr: mx_info_header_t,
pub rec: mx_record_process_t,
pub struct zx_info_process_t {
pub hdr: zx_info_header_t,
pub rec: zx_record_process_t,
}
extern {
pub fn mx_job_default() -> mx_handle_t;
pub fn zx_job_default() -> zx_handle_t;
pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;
pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;
pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;
pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;
pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
out: *const mx_handle_t) -> mx_handle_t;
pub fn zx_handle_duplicate(handle: zx_handle_t, rights: zx_rights_t,
out: *const zx_handle_t) -> zx_handle_t;
pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
pending: *mut mx_signals_t) -> mx_status_t;
pub fn zx_object_wait_one(handle: zx_handle_t, signals: zx_signals_t, timeout: zx_time_t,
pending: *mut zx_signals_t) -> zx_status_t;
pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
buffer_size: mx_size_t, actual_size: *mut mx_size_t,
avail: *mut mx_size_t) -> mx_status_t;
pub fn zx_object_get_info(handle: zx_handle_t, topic: u32, buffer: *mut c_void,
buffer_size: zx_size_t, actual_size: *mut zx_size_t,
avail: *mut zx_size_t) -> zx_status_t;
}
// From `enum special_handles` in system/ulib/launchpad/launchpad.c
@@ -133,117 +133,117 @@ pub struct launchpad_t {
env: *const c_char,
env_len: usize,
handles: *mut mx_handle_t,
handles: *mut zx_handle_t,
handles_info: *mut u32,
handle_count: usize,
handle_alloc: usize,
entry: mx_vaddr_t,
base: mx_vaddr_t,
vdso_base: mx_vaddr_t,
entry: zx_vaddr_t,
base: zx_vaddr_t,
vdso_base: zx_vaddr_t,
stack_size: usize,
special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
special_handles: [zx_handle_t; HND_SPECIAL_COUNT],
loader_message: bool,
}
extern {
pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
lp: *mut *mut launchpad_t) -> mx_status_t;
pub fn launchpad_create(job: zx_handle_t, name: *const c_char,
lp: *mut *mut launchpad_t) -> zx_status_t;
pub fn launchpad_go(lp: *mut launchpad_t,
proc_handle: *mut mx_handle_t,
err_msg: *mut *const c_char) -> mx_status_t;
proc_handle: *mut zx_handle_t,
err_msg: *mut *const c_char) -> zx_status_t;
pub fn launchpad_destroy(lp: *mut launchpad_t);
pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int,
argv: *const *const c_char) -> mx_status_t;
argv: *const *const c_char) -> zx_status_t;
pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;
pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> zx_status_t;
pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> mx_status_t;
pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> zx_status_t;
pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;
pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> zx_status_t;
pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
pub fn launchpad_vmo_from_file(filename: *const c_char) -> zx_handle_t;
}
// Launchpad clone constants
pub const LP_CLONE_MXIO_ROOT: u32 = 0x0001;
pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
// LP_CLONE_MXIO_STDIO = 0x0004
// LP_CLONE_MXIO_ALL = 0x00FF
pub const LP_CLONE_FDIO_NAMESPACE: u32 = 0x0001;
pub const LP_CLONE_FDIO_CWD: u32 = 0x0002;
// LP_CLONE_FDIO_STDIO = 0x0004
// LP_CLONE_FDIO_ALL = 0x00FF
// LP_CLONE_ENVIRON = 0x0100
// LP_CLONE_DEFAULT_JOB = 0x0200
// LP_CLONE_ALL = 0xFFFF
// Errors
#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1;
#[allow(unused)] pub const ERR_INTERNAL: zx_status_t = -1;
// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
// or enabled.
#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2;
#[allow(unused)] pub const ERR_NOT_SUPPORTED: zx_status_t = -2;
// ERR_NO_RESOURCES: The system was not able to allocate some resource
// needed for the operation.
#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3;
#[allow(unused)] pub const ERR_NO_RESOURCES: zx_status_t = -3;
// ERR_NO_MEMORY: The system was not able to allocate memory needed
// for the operation.
#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4;
#[allow(unused)] pub const ERR_NO_MEMORY: zx_status_t = -4;
// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete
// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete
// successfully.
#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5;
#[allow(unused)] pub const ERR_CALL_FAILED: zx_status_t = -5;
// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
// retried. This should not be seen outside of the VDSO.
#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6;
#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6;
// ======= Parameter errors =======
// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10;
#[allow(unused)] pub const ERR_INVALID_ARGS: zx_status_t = -10;
// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11;
#[allow(unused)] pub const ERR_BAD_HANDLE: zx_status_t = -11;
// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
// perform the operation.
// Example: Attempting a message_read on a thread handle.
#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12;
#[allow(unused)] pub const ERR_WRONG_TYPE: zx_status_t = -12;
// ERR_BAD_SYSCALL: The specified syscall number is invalid.
#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13;
#[allow(unused)] pub const ERR_BAD_SYSCALL: zx_status_t = -13;
// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
// operation.
#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14;
#[allow(unused)] pub const ERR_OUT_OF_RANGE: zx_status_t = -14;
// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
// this operation.
#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15;
#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15;
// ======= Precondition or state errors =======
// ERR_BAD_STATE: operation failed because the current state of the
// object does not allow it, or a precondition of the operation is
// not satisfied
#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20;
#[allow(unused)] pub const ERR_BAD_STATE: zx_status_t = -20;
// ERR_TIMED_OUT: The time limit for the operation elapsed before
// the operation completed.
#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21;
#[allow(unused)] pub const ERR_TIMED_OUT: zx_status_t = -21;
// ERR_SHOULD_WAIT: The operation cannot be performed currently but
// potentially could succeed if the caller waits for a prerequisite
@@ -253,67 +253,67 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
// Attempting to read from a message pipe that has no messages waiting
// and has a closed remote end will return ERR_REMOTE_CLOSED.
#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22;
#[allow(unused)] pub const ERR_SHOULD_WAIT: zx_status_t = -22;
// ERR_CANCELED: The in-progress operation (e.g. a wait) has been
// // canceled.
#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23;
#[allow(unused)] pub const ERR_CANCELED: zx_status_t = -23;
// ERR_PEER_CLOSED: The operation failed because the remote end
// of the subject of the operation was closed.
#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24;
#[allow(unused)] pub const ERR_PEER_CLOSED: zx_status_t = -24;
// ERR_NOT_FOUND: The requested entity is not found.
#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25;
#[allow(unused)] pub const ERR_NOT_FOUND: zx_status_t = -25;
// ERR_ALREADY_EXISTS: An object with the specified identifier
// already exists.
// Example: Attempting to create a file when a file already exists
// with that name.
#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26;
#[allow(unused)] pub const ERR_ALREADY_EXISTS: zx_status_t = -26;
// ERR_ALREADY_BOUND: The operation failed because the named entity
// is already owned or controlled by another entity. The operation
// could succeed later if the current owner releases the entity.
#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27;
#[allow(unused)] pub const ERR_ALREADY_BOUND: zx_status_t = -27;
// ERR_UNAVAILABLE: The subject of the operation is currently unable
// to perform the operation.
// Note: This is used when there's no direct way for the caller to
// observe when the subject will be able to perform the operation
// and should thus retry.
#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28;
#[allow(unused)] pub const ERR_UNAVAILABLE: zx_status_t = -28;
// ======= Permission check errors =======
// ERR_ACCESS_DENIED: The caller did not have permission to perform
// the specified operation.
#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30;
#[allow(unused)] pub const ERR_ACCESS_DENIED: zx_status_t = -30;
// ======= Input-output errors =======
// ERR_IO: Otherwise unspecified error occurred during I/O.
#[allow(unused)] pub const ERR_IO: mx_status_t = -40;
#[allow(unused)] pub const ERR_IO: zx_status_t = -40;
// ERR_REFUSED: The entity the I/O operation is being performed on
// rejected the operation.
// Example: an I2C device NAK'ing a transaction or a disk controller
// rejecting an invalid command.
#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41;
#[allow(unused)] pub const ERR_IO_REFUSED: zx_status_t = -41;
// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
// check and is possibly corrupted.
// Example: CRC or Parity error.
#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42;
#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42;
// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
// and may be permanently lost.
// Example: A disk block is irrecoverably damaged.
#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43;
#[allow(unused)] pub const ERR_IO_DATA_LOSS: zx_status_t = -43;
// Filesystem specific errors
#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50;
#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51;
#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52;
#[allow(unused)] pub const ERR_BAD_PATH: zx_status_t = -50;
#[allow(unused)] pub const ERR_NOT_DIR: zx_status_t = -51;
#[allow(unused)] pub const ERR_NOT_FILE: zx_status_t = -52;
// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53;
#[allow(unused)] pub const ERR_FILE_BIG: zx_status_t = -53;
// ERR_NO_SPACE: Filesystem or device space is exhausted.
#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54;
#[allow(unused)] pub const ERR_NO_SPACE: zx_status_t = -54;

View File

@@ -344,15 +344,15 @@ mod imp {
use io;
use rand::Rng;
#[link(name = "magenta")]
#[link(name = "zircon")]
extern {
fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
}
fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
unsafe {
let mut actual = 0;
let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
if status == 0 {
Ok(actual)
} else {
@@ -387,7 +387,7 @@ mod imp {
let ret = getrandom(buf);
match ret {
Err(err) => {
panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
err, buf.len())
}
Ok(actual) => {

View File

@@ -65,6 +65,31 @@ pub struct Guard {
/// each lock, but once a lock is poisoned then all future acquisitions will
/// return this error.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(1));
///
/// // poison the mutex
/// let c_mutex = mutex.clone();
/// let _ = thread::spawn(move || {
/// let mut data = c_mutex.lock().unwrap();
/// *data = 2;
/// panic!();
/// }).join();
///
/// match mutex.lock() {
/// Ok(_) => unreachable!(),
/// Err(p_err) => {
/// let data = p_err.get_ref();
/// println!("recovered: {}", data);
/// }
/// };
/// ```
///
/// [`Mutex`]: ../../std/sync/struct.Mutex.html
/// [`RwLock`]: ../../std/sync/struct.RwLock.html
#[stable(feature = "rust1", since = "1.0.0")]
@@ -72,10 +97,16 @@ pub struct PoisonError<T> {
guard: T,
}
/// An enumeration of possible errors which can occur while calling the
/// [`try_lock`] method.
/// An enumeration of possible errors associated with a [`TryLockResult`] which
/// can occur while trying to aquire a lock, from the [`try_lock`] method on a
/// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`].
///
/// [`Mutex`]: struct.Mutex.html
/// [`RwLock`]: struct.RwLock.html
/// [`TryLockResult`]: type.TryLockResult.html
/// [`try_lock`]: struct.Mutex.html#method.try_lock
/// [`try_read`]: struct.RwLock.html#method.try_read
/// [`try_write`]: struct.RwLock.html#method.try_write
#[stable(feature = "rust1", since = "1.0.0")]
pub enum TryLockError<T> {
/// The lock could not be acquired because another thread failed while holding
@@ -148,6 +179,28 @@ impl<T> PoisonError<T> {
/// Consumes this error indicating that a lock is poisoned, returning the
/// underlying guard to allow access regardless.
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// let mutex = Arc::new(Mutex::new(HashSet::new()));
///
/// // poison the mutex
/// let c_mutex = mutex.clone();
/// let _ = thread::spawn(move || {
/// let mut data = c_mutex.lock().unwrap();
/// data.insert(10);
/// panic!();
/// }).join();
///
/// let p_err = mutex.lock().unwrap_err();
/// let data = p_err.into_inner();
/// println!("recovered {} items", data.len());
/// ```
#[stable(feature = "sync_poison", since = "1.2.0")]
pub fn into_inner(self) -> T { self.guard }

View File

@@ -13,7 +13,9 @@ use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
const NANOS_PER_SEC: u32 = 1_000_000_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
const NANOS_PER_MICRO: u32 = 1_000;
const MILLIS_PER_SEC: u64 = 1_000;
const MICROS_PER_SEC: u64 = 1_000_000;
/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
@@ -116,6 +118,27 @@ impl Duration {
Duration { secs: secs, nanos: nanos }
}
/// Creates a new `Duration` from the specified number of microseconds.
///
/// # Examples
///
/// ```
/// #![feature(duration_from_micros)]
/// use std::time::Duration;
///
/// let duration = Duration::from_micros(1_000_002);
///
/// assert_eq!(1, duration.as_secs());
/// assert_eq!(2000, duration.subsec_nanos());
/// ```
#[unstable(feature = "duration_from_micros", issue = "44400")]
#[inline]
pub fn from_micros(micros: u64) -> Duration {
let secs = micros / MICROS_PER_SEC;
let nanos = ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO;
Duration { secs: secs, nanos: nanos }
}
/// Returns the number of _whole_ seconds contained by this `Duration`.
///
/// The returned value does not include the fractional (nanosecond) part of the