@@ -17,7 +17,7 @@

use core::num;
use intrinsics;
use libc::c_int;
use os::raw::c_int;
use num::{FpCategory, ParseFloatError};

pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
@@ -28,7 +28,7 @@ pub use core::f32::consts;

#[allow(dead_code)]
mod cmath {
use libc::{c_float, c_int};
use os::raw::{c_float, c_int};

extern {
pub fn cbrtf(n: c_float) -> c_float;
@@ -72,7 +72,7 @@ mod cmath {
pub use self::shims::*;
#[cfg(target_env = "msvc")]
mod shims {
use libc::{c_float, c_int};
use os::raw::{c_float, c_int};

pub unsafe fn acosf(n: c_float) -> c_float {
f64::acos(n as f64) as c_float
@@ -16,8 +16,8 @@
#![allow(missing_docs)]

use core::num;
use os::raw::c_int;
use intrinsics;
use libc::c_int;
use num::{FpCategory, ParseFloatError};

pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
@@ -28,7 +28,7 @@ pub use core::f64::consts;

#[allow(dead_code)]
mod cmath {
use libc::{c_double, c_int};
use os::raw::{c_double, c_int};

#[link_name = "m"]
extern {
@@ -12,11 +12,11 @@

#![stable(feature = "rust1", since = "1.0.0")]

use sys::inner::prelude::*;
use sys::os_str::prelude as sys;
use ffi::{OsStr, OsString};
use vec::Vec;
use mem;
use prelude::v1::*;
use sys::os_str::Buf;
use sys_common::{FromInner, IntoInner, AsInner};

/// Unix-specific extensions to `OsString`.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -33,7 +33,7 @@ pub trait OsStringExt {
#[stable(feature = "rust1", since = "1.0.0")]
impl OsStringExt for OsString {
fn from_vec(vec: Vec<u8>) -> OsString {
FromInner::from_inner(Buf { inner: vec })
FromInner::from_inner(sys::OsString::from_vec(vec))
}
fn into_vec(self) -> Vec<u8> {
self.into_inner().inner
@@ -44,6 +44,7 @@ impl OsStringExt for OsString {
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStrExt {
#[stable(feature = "rust1", since = "1.0.0")]
/// Creates an `OsStr from a byte slice.
fn from_bytes(slice: &[u8]) -> &Self;

/// Gets the underlying byte view of the `OsStr` slice.
@@ -0,0 +1,260 @@
// Copyright 2015 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.

//! Unix-specific extensions to primitives in the `std::fs` module.

#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]

use sys::inner::prelude::*;
use sys::fs::prelude::*;
use fs;
use io;
use os::raw::c_long;
use os::unix::raw;
use path::Path;
use sys;

#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const USER_READ: raw::mode_t = 0o400;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const USER_WRITE: raw::mode_t = 0o200;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const USER_EXECUTE: raw::mode_t = 0o100;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const USER_RWX: raw::mode_t = 0o700;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const GROUP_READ: raw::mode_t = 0o040;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const GROUP_WRITE: raw::mode_t = 0o020;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const GROUP_EXECUTE: raw::mode_t = 0o010;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const GROUP_RWX: raw::mode_t = 0o070;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const OTHER_READ: raw::mode_t = 0o004;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const OTHER_WRITE: raw::mode_t = 0o002;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const OTHER_EXECUTE: raw::mode_t = 0o001;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const OTHER_RWX: raw::mode_t = 0o007;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const ALL_READ: raw::mode_t = 0o444;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const ALL_WRITE: raw::mode_t = 0o222;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const ALL_EXECUTE: raw::mode_t = 0o111;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const ALL_RWX: raw::mode_t = 0o777;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const SETUID: raw::mode_t = 0o4000;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const SETGID: raw::mode_t = 0o2000;
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
pub const STICKY_BIT: raw::mode_t = 0o1000;

/// 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.
#[stable(feature = "fs_ext", since = "1.1.0")]
fn mode(&self) -> raw::mode_t;

/// Sets the underlying raw `mode_t` bits for this set of permissions.
#[stable(feature = "fs_ext", since = "1.1.0")]
fn set_mode(&mut self, mode: raw::mode_t);

/// Creates a new instance of `Permissions` from the given set of Unix
/// permission bits.
#[stable(feature = "fs_ext", since = "1.1.0")]
fn from_mode(mode: raw::mode_t) -> Self;
}

#[stable(feature = "fs_ext", since = "1.1.0")]
impl PermissionsExt for fs::Permissions {
fn mode(&self) -> raw::mode_t { self.as_inner().mode() }

fn set_mode(&mut self, mode: raw::mode_t) {
*self = FromInner::from_inner(FromInner::from_inner(mode));
}

fn from_mode(mode: raw::mode_t) -> fs::Permissions {
FromInner::from_inner(FromInner::from_inner(mode))
}
}

/// Unix-specific extensions to `OpenOptions`
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait OpenOptionsExt {
/// Sets the mode bits that a new file will be created with.
///
/// If a new file is created as part of a `File::open_opts` call then this
/// specified `mode` will be used as the permission bits for the new file.
#[stable(feature = "fs_ext", since = "1.1.0")]
fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
}

#[stable(feature = "fs_ext", since = "1.1.0")]
impl OpenOptionsExt for fs::OpenOptions {
fn mode(&mut self, mode: raw::mode_t) -> &mut fs::OpenOptions {
self.as_inner_mut().mode(mode); self
}
}

// Hm, why are there casts here to the returned type, shouldn't the types always
// be the same? Right you are! Turns out, however, on android at least the types
// in the raw `stat` structure are not the same as the types being returned. Who
// knew!
//
// As a result to make sure this compiles for all platforms we do the manual
// casts and rely on manual lowering to `stat` if the raw type is desired.
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn dev(&self) -> raw::dev_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ino(&self) -> raw::ino_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mode(&self) -> raw::mode_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn nlink(&self) -> raw::nlink_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn uid(&self) -> raw::uid_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn gid(&self) -> raw::gid_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn rdev(&self) -> raw::dev_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn size(&self) -> raw::off_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn atime(&self) -> raw::time_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn atime_nsec(&self) -> c_long;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mtime(&self) -> raw::time_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn mtime_nsec(&self) -> c_long;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ctime(&self) -> raw::time_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn ctime_nsec(&self) -> c_long;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn blksize(&self) -> raw::blksize_t;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn blocks(&self) -> raw::blkcnt_t;
}

impl MetadataExt for fs::Metadata {
fn dev(&self) -> raw::dev_t { self.as_inner().as_inner().st_dev as raw::dev_t }
fn ino(&self) -> raw::ino_t { self.as_inner().as_inner().st_ino as raw::ino_t }
fn mode(&self) -> raw::mode_t { self.as_inner().as_inner().st_mode as raw::mode_t }
fn nlink(&self) -> raw::nlink_t { self.as_inner().as_inner().st_nlink as raw::nlink_t }
fn uid(&self) -> raw::uid_t { self.as_inner().as_inner().st_uid as raw::uid_t }
fn gid(&self) -> raw::gid_t { self.as_inner().as_inner().st_gid as raw::gid_t }
fn rdev(&self) -> raw::dev_t { self.as_inner().as_inner().st_rdev as raw::dev_t }
fn size(&self) -> raw::off_t { self.as_inner().as_inner().st_size as raw::off_t }
fn atime(&self) -> raw::time_t { self.as_inner().as_inner().st_atime }
fn atime_nsec(&self) -> c_long { self.as_inner().as_inner().st_atime_nsec as c_long }
fn mtime(&self) -> raw::time_t { self.as_inner().as_inner().st_mtime }
fn mtime_nsec(&self) -> c_long { self.as_inner().as_inner().st_mtime_nsec as c_long }
fn ctime(&self) -> raw::time_t { self.as_inner().as_inner().st_ctime }
fn ctime_nsec(&self) -> c_long { self.as_inner().as_inner().st_ctime_nsec as c_long }

fn blksize(&self) -> raw::blksize_t {
self.as_inner().as_inner().st_blksize as raw::blksize_t
}
fn blocks(&self) -> raw::blkcnt_t {
self.as_inner().as_inner().st_blocks as raw::blkcnt_t
}
}

/// Add special unix types (block/char device, fifo and socket)
#[unstable(feature = "file_type_ext", reason = "recently added API",
issue = "27796")]
pub trait FileTypeExt {
/// Returns whether this file type is a block device.
fn is_block_device(&self) -> bool;
/// Returns whether this file type is a char device.
fn is_char_device(&self) -> bool;
/// Returns whether this file type is a fifo.
fn is_fifo(&self) -> bool;
/// Returns whether this file type is a socket.
fn is_socket(&self) -> bool;
}

#[unstable(feature = "file_type_ext", reason = "recently added API",
issue = "27796")]
impl FileTypeExt for fs::FileType {
fn is_block_device(&self) -> bool { self.as_inner().is_block_device() }
fn is_char_device(&self) -> bool { self.as_inner().is_char_device() }
fn is_fifo(&self) -> bool { self.as_inner().is_fifo() }
fn is_socket(&self) -> bool { self.as_inner().is_socket() }
}

/// Unix-specific extension methods for `fs::DirEntry`
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
pub trait DirEntryExt {
/// Returns the underlying `d_ino` field in the contained `dirent`
/// structure.
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
fn ino(&self) -> raw::ino_t;
}

impl DirEntryExt for fs::DirEntry {
fn ino(&self) -> raw::ino_t { self.as_inner().ino() }
}

/// Creates a new symbolic link on the filesystem.
///
/// The `dst` path will be a symbolic link pointing to the `src` path.
///
/// # Note
///
/// On Windows, you must specify whether a symbolic link points to a file
/// or directory. Use `os::windows::fs::symlink_file` to create a
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
/// symbolic link to a directory. Additionally, the process must have
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
/// symbolic link.
///
/// # Examples
///
/// ```
/// use std::os::unix::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// try!(fs::symlink("a.txt", "b.txt"));
/// # Ok(())
/// # }
/// ```
#[stable(feature = "symlink", since = "1.1.0")]
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
{
Fs::symlink(src.as_ref().as_os_str().as_inner(), dst.as_ref().as_os_str().as_inner()).map_err(From::from)
}

#[unstable(feature = "dir_builder", reason = "recently added API",
issue = "27710")]
/// An extension trait for `fs::DirBuilder` for unix-specific options.
pub trait DirBuilderExt {
/// Sets the mode to create new directories with. This option defaults to
/// 0o777.
fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
}

impl DirBuilderExt for fs::DirBuilder {
fn mode(&mut self, mode: raw::mode_t) -> &mut fs::DirBuilder {
self.as_inner_mut().set_mode(mode);
self
}
}

@@ -12,11 +12,13 @@

#![stable(feature = "rust1", since = "1.0.0")]

use sys::inner::prelude::*;
use sys::net::prelude as sys_net;
use sys::fs::prelude as sys_fs;
use fs;
use net;
use os::raw;
use sys;
use sys_common::{self, AsInner, FromInner, IntoInner};

/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -75,72 +77,69 @@ pub trait IntoRawFd {
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
fn as_raw_fd(&self) -> RawFd {
self.as_inner().fd().raw()
*self.as_inner().as_inner()
}
}
#[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::fs::File::from_inner(fd))
fs::File::from_inner(sys_fs::File::from_inner(fd))
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_fd().into_raw()
self.into_inner().into_inner()
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpStream {
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpListener {
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::UdpSocket {
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner() }
}

#[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(sys_common::net::TcpStream::from_inner(socket))
net::TcpStream::from_inner(FromInner::from_inner(fd))
}
}
#[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(sys_common::net::TcpListener::from_inner(socket))
net::TcpListener::from_inner(FromInner::from_inner(fd))
}
}
#[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(sys_common::net::UdpSocket::from_inner(socket))
net::UdpSocket::from_inner(FromInner::from_inner(fd))
}
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpStream {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_socket().into_inner()
self.into_inner().into_inner()
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpListener {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_socket().into_inner()
self.into_inner().into_inner()
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::UdpSocket {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_socket().into_inner()
self.into_inner().into_inner()
}
}
@@ -0,0 +1,53 @@
// Copyright 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.

//! Experimental extensions to `std` for Unix platforms.
//!
//! For now, this module is limited to extracting file descriptors,
//! but its functionality will grow over time.
//!
//! # Example
//!
//! ```no_run
//! use std::fs::File;
//! use std::os::unix::prelude::*;
//!
//! fn main() {
//! let f = File::create("foo.txt").unwrap();
//! let fd = f.as_raw_fd();
//!
//! // use fd with native unix bindings
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

pub mod io;
pub mod ffi;
pub mod fs;
pub mod process;
pub use sys::unix::raw;

/// A prelude for conveniently writing platform-specific code.
///
/// Includes all extension traits, and some important type definitions.
#[stable(feature = "rust1", since = "1.0.0")]
pub mod prelude {
#[doc(no_inline)]
pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
pub use super::ffi::{OsStrExt, OsStringExt};
#[doc(no_inline)]
pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt};
#[doc(no_inline)]
pub use super::fs::{DirEntryExt};
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
pub use super::process::{CommandExt, ExitStatusExt};
}
@@ -12,11 +12,11 @@

#![stable(feature = "rust1", since = "1.0.0")]

use sys::inner::prelude::*;
use sys::process::prelude as sys;
use os::unix::raw::{uid_t, gid_t};
use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
use process;
use sys;
use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};

/// Unix-specific extensions to the `std::process::Command` builder
#[stable(feature = "rust1", since = "1.0.0")]
@@ -25,12 +25,12 @@ pub trait CommandExt {
/// `setuid` call in the child process. Failure in the `setuid`
/// call will cause the spawn to fail.
#[stable(feature = "rust1", since = "1.0.0")]
fn uid(&mut self, id: uid_t) -> &mut process::Command;
fn uid(&mut self, id: uid_t) -> &mut Self;

/// Similar to `uid`, but sets the group id of the child process. This has
/// the same semantics as the `uid` field.
#[stable(feature = "rust1", since = "1.0.0")]
fn gid(&mut self, id: gid_t) -> &mut process::Command;
fn gid(&mut self, id: gid_t) -> &mut Self;

/// Create a new session (cf. `setsid(2)`) for the child process. This means
/// that the child is the leader of a new process group. The parent process
@@ -43,7 +43,7 @@ pub trait CommandExt {
/// (the daemon) in the same session.
#[unstable(feature = "process_session_leader", reason = "recently added",
issue = "27811")]
fn session_leader(&mut self, on: bool) -> &mut process::Command;
fn session_leader(&mut self, on: bool) -> &mut Self;
}

#[stable(feature = "rust1", since = "1.0.0")]
@@ -76,7 +76,7 @@ pub trait ExitStatusExt {
impl ExitStatusExt for process::ExitStatus {
fn signal(&self) -> Option<i32> {
match *self.as_inner() {
sys::process::ExitStatus::Signal(s) => Some(s),
sys::ExitStatus::Signal(s) => Some(s),
_ => None
}
}
@@ -85,45 +85,45 @@ impl ExitStatusExt for process::ExitStatus {
#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawFd for process::Stdio {
unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
process::Stdio::from_inner(sys::fd::FileDesc::new(fd))
process::Stdio::from_inner(fd)
}
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdin {
fn as_raw_fd(&self) -> RawFd {
self.as_inner().fd().raw()
*self.as_inner().as_inner()
}
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdout {
fn as_raw_fd(&self) -> RawFd {
self.as_inner().fd().raw()
*self.as_inner().as_inner()
}
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStderr {
fn as_raw_fd(&self) -> RawFd {
self.as_inner().fd().raw()
*self.as_inner().as_inner()
}
}

impl IntoRawFd for process::ChildStdin {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_fd().into_raw()
self.into_inner().into_inner()
}
}

impl IntoRawFd for process::ChildStdout {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_fd().into_raw()
self.into_inner().into_inner()
}
}

impl IntoRawFd for process::ChildStderr {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_fd().into_raw()
self.into_inner().into_inner()
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -98,6 +98,10 @@

#![stable(feature = "rust1", since = "1.0.0")]

use sys::path::traits::*;
use sys::path::prelude as sys;
use sys::inner::prelude::*;

use ascii::*;
use borrow::{Borrow, IntoCow, ToOwned, Cow};
use cmp;
@@ -110,8 +114,6 @@ use fmt;

use ffi::{OsStr, OsString};

use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};

////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES
////////////////////////////////////////////////////////////////////////////////
@@ -122,132 +124,6 @@ use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
// OsStr APIs for parsing, but it will take a while for those to become
// available.

////////////////////////////////////////////////////////////////////////////////
// Platform-specific definitions
////////////////////////////////////////////////////////////////////////////////

// The following modules give the most basic tools for parsing paths on various
// platforms. The bulk of the code is devoted to parsing prefixes on Windows.

#[cfg(unix)]
mod platform {
use super::Prefix;
use ffi::OsStr;

#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/'
}

#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'/'
}

pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
None
}

pub const MAIN_SEP_STR: &'static str = "/";
pub const MAIN_SEP: char = '/';
}

#[cfg(windows)]
mod platform {
use ascii::*;

use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix};
use ffi::OsStr;

#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/' || b == b'\\'
}

#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'\\'
}

pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
use super::Prefix::*;
unsafe {
// The unsafety here stems from converting between &OsStr and &[u8]
// and back. This is safe to do because (1) we only look at ASCII
// contents of the encoding and (2) new &OsStr values are produced
// only from ASCII-bounded slices of existing &OsStr values.
let mut path = os_str_as_u8_slice(path);

if path.starts_with(br"\\") {
// \\
path = &path[2..];
if path.starts_with(br"?\") {
// \\?\
path = &path[2..];
if path.starts_with(br"UNC\") {
// \\?\UNC\server\share
path = &path[4..];
let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
Some((server, share)) => (u8_slice_as_os_str(server),
u8_slice_as_os_str(share)),
None => (u8_slice_as_os_str(path),
u8_slice_as_os_str(&[])),
};
return Some(VerbatimUNC(server, share));
} else {
// \\?\path
let idx = path.iter().position(|&b| b == b'\\');
if idx == Some(2) && path[1] == b':' {
let c = path[0];
if c.is_ascii() && (c as char).is_alphabetic() {
// \\?\C:\ path
return Some(VerbatimDisk(c.to_ascii_uppercase()));
}
}
let slice = &path[.. idx.unwrap_or(path.len())];
return Some(Verbatim(u8_slice_as_os_str(slice)));
}
} else if path.starts_with(b".\\") {
// \\.\path
path = &path[2..];
let pos = path.iter().position(|&b| b == b'\\');
let slice = &path[..pos.unwrap_or(path.len())];
return Some(DeviceNS(u8_slice_as_os_str(slice)));
}
match parse_two_comps(path, is_sep_byte) {
Some((server, share)) if !server.is_empty() && !share.is_empty() => {
// \\server\share
return Some(UNC(u8_slice_as_os_str(server),
u8_slice_as_os_str(share)));
}
_ => ()
}
} else if path.len() > 1 && path[1] == b':' {
// C:
let c = path[0];
if c.is_ascii() && (c as char).is_alphabetic() {
return Some(Disk(c.to_ascii_uppercase()));
}
}
return None;
}

fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
let first = match path.iter().position(|x| f(*x)) {
None => return None,
Some(x) => &path[.. x]
};
path = &path[(first.len()+1)..];
let idx = path.iter().position(|x| f(*x));
let second = &path[.. idx.unwrap_or(path.len())];
Some((first, second))
}
}

pub const MAIN_SEP_STR: &'static str = "\\";
pub const MAIN_SEP: char = '\\';
}

////////////////////////////////////////////////////////////////////////////////
// Windows Prefixes
////////////////////////////////////////////////////////////////////////////////
@@ -287,6 +163,19 @@ pub enum Prefix<'a> {
Disk(u8),
}

impl<'a> FromInner<sys::Prefix<'a>> for Prefix<'a> {
fn from_inner(p: sys::Prefix<'a>) -> Self {
match p {
sys::Prefix::Verbatim(p) => Prefix::Verbatim(FromInner::from_inner(p)),
sys::Prefix::VerbatimUNC(p, s) => Prefix::VerbatimUNC(FromInner::from_inner(p), FromInner::from_inner(s)),
sys::Prefix::VerbatimDisk(p) => Prefix::VerbatimDisk(p),
sys::Prefix::DeviceNS(p) => Prefix::DeviceNS(FromInner::from_inner(p)),
sys::Prefix::UNC(p, s) => Prefix::UNC(FromInner::from_inner(p), FromInner::from_inner(s)),
sys::Prefix::Disk(p) => Prefix::Disk(p),
}
}
}

impl<'a> Prefix<'a> {
#[inline]
fn len(&self) -> usize {
@@ -351,12 +240,12 @@ impl<'a> Prefix<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_separator(c: char) -> bool {
c.is_ascii() && is_sep_byte(c as u8)
c.is_ascii() && sys::PathInfo::is_sep_byte(c as u8)
}

/// The primary separator for the current platform
#[stable(feature = "rust1", since = "1.0.0")]
pub const MAIN_SEPARATOR: char = platform::MAIN_SEP;
pub const MAIN_SEPARATOR: char = sys::PathInfo::MAIN_SEP;

////////////////////////////////////////////////////////////////////////////////
// Misc helpers
@@ -397,7 +286,7 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
/// Says whether the first byte after the prefix is a separator.
fn has_physical_root(s: &[u8], prefix: Option<Prefix>) -> bool {
let path = if let Some(p) = prefix { &s[p.len()..] } else { s };
!path.is_empty() && is_sep_byte(path[0])
!path.is_empty() && sys::PathInfo::is_sep_byte(path[0])
}

// basic workhorse for splitting stem and extension
@@ -524,7 +413,7 @@ impl<'a> Component<'a> {
pub fn as_os_str(self) -> &'a OsStr {
match self {
Component::Prefix(p) => p.as_os_str(),
Component::RootDir => OsStr::new(MAIN_SEP_STR),
Component::RootDir => OsStr::new(sys::PathInfo::MAIN_SEP_STR),
Component::CurDir => OsStr::new("."),
Component::ParentDir => OsStr::new(".."),
Component::Normal(path) => path,
@@ -621,9 +510,9 @@ impl<'a> Components<'a> {
#[inline]
fn is_sep_byte(&self, b: u8) -> bool {
if self.prefix_verbatim() {
is_verbatim_sep(b)
sys::PathInfo::is_verbatim_sep(b)
} else {
is_sep_byte(b)
sys::PathInfo::is_sep_byte(b)
}
}

@@ -969,7 +858,7 @@ impl PathBuf {

fn _push(&mut self, path: &Path) {
// in general, a separator is needed if the rightmost byte is not a separator
let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
let mut need_sep = self.as_mut_vec().last().map(|c| !sys::PathInfo::is_sep_byte(*c)).unwrap_or(false);

// in the special case of `C:` on Windows, do *not* add a separator
{
@@ -993,7 +882,7 @@ impl PathBuf {

// `path` is a pure relative path
} else if need_sep {
self.inner.push(MAIN_SEP_STR);
self.inner.push(sys::PathInfo::MAIN_SEP_STR);
}

self.inner.push(path);
@@ -1349,7 +1238,7 @@ impl Path {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_absolute(&self) -> bool {
self.has_root() &&
(cfg!(unix) || self.prefix().is_some())
(!sys::PathInfo::PREFIX_IMP || self.prefix().is_some())
}

/// A path is *relative* if it is not absolute.
@@ -1644,7 +1533,8 @@ impl Path {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn components(&self) -> Components {
let prefix = parse_prefix(self.as_os_str());
let prefix = sys::PathInfo::parse_prefix(self.as_os_str().as_inner());
let prefix = prefix.map(FromInner::from_inner);
Components {
path: self.as_u8_slice(),
prefix: prefix,

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -57,6 +57,9 @@

#![unstable(feature = "rand", issue = "0")]

use sys::rand::traits::*;
use sys::rand::prelude as sys;

use cell::RefCell;
use io;
use mem;
@@ -70,7 +73,6 @@ use core_rand::Isaac64Rng as IsaacWordRng;
pub use core_rand::{Rand, Rng, SeedableRng};
pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
pub use core_rand::reseeding;
pub use rand::os::OsRng;

pub mod os;
pub mod reader;
@@ -95,7 +97,7 @@ impl StdRng {
/// Reading the randomness from the OS may fail, and any error is
/// propagated via the `io::Result` return value.
pub fn new() -> io::Result<StdRng> {
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
sys::Rng::new().map(|mut r| StdRng { rng: r.gen() }).map_err(From::from)
}
}

@@ -11,344 +11,15 @@
//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
use self::OsRngInner::*;

use fs::File;
use io;
use libc;
use mem;
use rand::Rng;
use rand::reader::ReaderRng;
use sys::os::errno;

#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "powerpc")))]
fn getrandom(buf: &mut [u8]) -> libc::c_long {
extern "C" {
fn syscall(number: libc::c_long, ...) -> libc::c_long;
}

#[cfg(target_arch = "x86_64")]
const NR_GETRANDOM: libc::c_long = 318;
#[cfg(target_arch = "x86")]
const NR_GETRANDOM: libc::c_long = 355;
#[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
const NR_GETRANDOM: libc::c_long = 384;
#[cfg(any(target_arch = "aarch64"))]
const NR_GETRANDOM: libc::c_long = 278;

unsafe {
syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0)
}
}

#[cfg(not(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "powerpc"))))]
fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

fn getrandom_fill_bytes(v: &mut [u8]) {
let mut read = 0;
let len = v.len();
while read < len {
let result = getrandom(&mut v[read..]);
if result == -1 {
let err = errno() as libc::c_int;
if err == libc::EINTR {
continue;
} else {
panic!("unexpected getrandom error: {}", err);
}
} else {
read += result as usize;
}
}
}

fn getrandom_next_u32() -> u32 {
let mut buf: [u8; 4] = [0; 4];
getrandom_fill_bytes(&mut buf);
unsafe { mem::transmute::<[u8; 4], u32>(buf) }
}

fn getrandom_next_u64() -> u64 {
let mut buf: [u8; 8] = [0; 8];
getrandom_fill_bytes(&mut buf);
unsafe { mem::transmute::<[u8; 8], u64>(buf) }
}

#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "powerpc")))]
fn is_getrandom_available() -> bool {
use sync::atomic::{AtomicBool, Ordering};
use sync::Once;

static CHECKER: Once = Once::new();
static AVAILABLE: AtomicBool = AtomicBool::new(false);

CHECKER.call_once(|| {
let mut buf: [u8; 0] = [];
let result = getrandom(&mut buf);
let available = if result == -1 {
let err = io::Error::last_os_error().raw_os_error();
err != Some(libc::ENOSYS)
} else {
true
};
AVAILABLE.store(available, Ordering::Relaxed);
});

AVAILABLE.load(Ordering::Relaxed)
}

#[cfg(not(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "powerpc"))))]
fn is_getrandom_available() -> bool { false }

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
///
/// This does not block.
pub struct OsRng {
inner: OsRngInner,
}

enum OsRngInner {
OsGetrandomRng,
OsReaderRng(ReaderRng<File>),
}

impl OsRng {
/// Create a new `OsRng`.
pub fn new() -> io::Result<OsRng> {
if is_getrandom_available() {
return Ok(OsRng { inner: OsGetrandomRng });
}

let reader = try!(File::open("/dev/urandom"));
let reader_rng = ReaderRng::new(reader);

Ok(OsRng { inner: OsReaderRng(reader_rng) })
}
}

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
match self.inner {
OsGetrandomRng => getrandom_next_u32(),
OsReaderRng(ref mut rng) => rng.next_u32(),
}
}
fn next_u64(&mut self) -> u64 {
match self.inner {
OsGetrandomRng => getrandom_next_u64(),
OsReaderRng(ref mut rng) => rng.next_u64(),
}
}
fn fill_bytes(&mut self, v: &mut [u8]) {
match self.inner {
OsGetrandomRng => getrandom_fill_bytes(v),
OsReaderRng(ref mut rng) => rng.fill_bytes(v)
}
}
}
}

#[cfg(target_os = "ios")]
mod imp {
#[cfg(stage0)] use prelude::v1::*;

use io;
use mem;
use ptr;
use rand::Rng;
use libc::{c_int, size_t};

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
///
/// This does not block.
pub struct OsRng {
// dummy field to ensure that this struct cannot be constructed outside
// of this module
_dummy: (),
}

enum SecRandom {}

#[allow(non_upper_case_globals)]
const kSecRandomDefault: *const SecRandom = ptr::null();

#[link(name = "Security", kind = "framework")]
extern "C" {
fn SecRandomCopyBytes(rnd: *const SecRandom,
count: size_t, bytes: *mut u8) -> c_int;
}

impl OsRng {
/// Create a new `OsRng`.
pub fn new() -> io::Result<OsRng> {
Ok(OsRng { _dummy: () })
}
}

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0; 4];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0; 8];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn fill_bytes(&mut self, v: &mut [u8]) {
let ret = unsafe {
SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
v.as_mut_ptr())
};
if ret == -1 {
panic!("couldn't generate random bytes: {}",
io::Error::last_os_error());
}
}
}
}

#[cfg(windows)]
mod imp {
use io;
use mem;
use rand::Rng;
use libc::types::os::arch::extra::{LONG_PTR};
use libc::{DWORD, BYTE, LPCSTR, BOOL};

type HCRYPTPROV = LONG_PTR;

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
///
/// This does not block.
pub struct OsRng {
hcryptprov: HCRYPTPROV
}

const PROV_RSA_FULL: DWORD = 1;
const CRYPT_SILENT: DWORD = 64;
const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

#[allow(non_snake_case)]
#[link(name = "advapi32")]
extern "system" {
fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
pszContainer: LPCSTR,
pszProvider: LPCSTR,
dwProvType: DWORD,
dwFlags: DWORD) -> BOOL;
fn CryptGenRandom(hProv: HCRYPTPROV,
dwLen: DWORD,
pbBuffer: *mut BYTE) -> BOOL;
fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
}

impl OsRng {
/// Create a new `OsRng`.
pub fn new() -> io::Result<OsRng> {
let mut hcp = 0;
let ret = unsafe {
CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
};

if ret == 0 {
Err(io::Error::last_os_error())
} else {
Ok(OsRng { hcryptprov: hcp })
}
}
}

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0; 4];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0; 8];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn fill_bytes(&mut self, v: &mut [u8]) {
let ret = unsafe {
CryptGenRandom(self.hcryptprov, v.len() as DWORD,
v.as_mut_ptr())
};
if ret == 0 {
panic!("couldn't generate random bytes: {}",
io::Error::last_os_error());
}
}
}

impl Drop for OsRng {
fn drop(&mut self) {
let ret = unsafe {
CryptReleaseContext(self.hcryptprov, 0)
};
if ret == 0 {
panic!("couldn't release context: {}",
io::Error::last_os_error());
}
}
}
}
pub use sys::rand::prelude::Rng as OsRng;

#[cfg(test)]
mod tests {
use prelude::v1::*;

use sync::mpsc::channel;
use rand::Rng;
use sys::rand::Rng as SysRng;
use super::OsRng;
use thread;

This file was deleted.

Oops, something went wrong.
@@ -12,10 +12,10 @@
//!
//! Documentation can be found on the `rt::at_exit` function.

use sys::sync::prelude::*;
use alloc::boxed::FnBox;
use boxed::Box;
use ptr;
use sys_common::mutex::Mutex;
use vec::Vec;

type Queue = Vec<Box<FnBox()>>;
@@ -67,7 +67,7 @@ pub fn cleanup() {
}
}

pub fn push(f: Box<FnBox()>) -> bool {
fn push(f: Box<FnBox()>) -> bool {
let mut ret = true;
unsafe {
LOCK.lock();
@@ -80,3 +80,7 @@ pub fn push(f: Box<FnBox()>) -> bool {
}
ret
}

pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
if push(Box::new(f)) {Ok(())} else {Err(())}
}
@@ -8,60 +8,51 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use env;
use io::prelude::*;
use sys::inner::prelude::*;
use sys::io::traits::*;
use sys::error::prelude as sys_error;
use sys::backtrace as sys;
use sys::io as sys_io;
use fmt::{self, Write as fmt_Write};
use io;
use libc;
use str;
use sync::atomic::{self, Ordering};

pub use sys::backtrace::write;

#[cfg(target_pointer_width = "64")]
pub const HEX_WIDTH: usize = 18;

#[cfg(target_pointer_width = "32")]
pub const HEX_WIDTH: usize = 10;

// For now logging is turned off by default, and this function checks to see
// whether the magical environment variable is present to see if it's turned on.
pub fn log_enabled() -> bool {
static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
match ENABLED.load(Ordering::SeqCst) {
1 => return false,
2 => return true,
_ => {}
pub struct BacktraceOutput<W>(pub W);
impl<W: Write> fmt_Write for BacktraceOutput<W> {
fn write_str(&mut self, v: &str) -> fmt::Result {
self.0.write(v.as_bytes()).map(drop).map_err(|_| fmt::Error)
}

let val = match env::var_os("RUST_BACKTRACE") {
Some(..) => 2,
None => 1,
};
ENABLED.store(val, Ordering::SeqCst);
val == 2
}

// These output functions should now be used everywhere to ensure consistency.
pub fn output(w: &mut Write, idx: isize, addr: *mut libc::c_void,
s: Option<&[u8]>) -> io::Result<()> {
try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH));
match s.and_then(|s| str::from_utf8(s).ok()) {
Some(string) => try!(demangle(w, string)),
None => try!(write!(w, "<unknown>")),
impl<W: Write> sys::BacktraceOutput for BacktraceOutput<W> {
fn output(&mut self, idx: isize, addr: *mut (),
s: Option<&[u8]>) -> sys_error::Result<()> {
try!(write!(self, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH));
match s.and_then(|s| str::from_utf8(s).ok()) {
Some(string) => try!(demangle(&mut self.0, string).map_err(IntoInner::into_inner)),
None => try!(write!(self, "<unknown>")),
}
self.0.write_all(&['\n' as u8]).map_err(IntoInner::into_inner)
}
w.write_all(&['\n' as u8])
}

#[allow(dead_code)]
pub fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
more: bool) -> io::Result<()> {
let file = str::from_utf8(file).unwrap_or("<unknown>");
// prior line: " ##: {:2$} - func"
try!(write!(w, " {:3$}at {}:{}", "", file, line, HEX_WIDTH));
if more {
try!(write!(w, " <... and possibly more>"));
fn output_fileline(&mut self, file: &[u8], line: i32,
more: bool) -> sys_error::Result<()> {
let file = str::from_utf8(file).unwrap_or("<unknown>");
// prior line: " ##: {:2$} - func"
try!(write!(self, " {:3$}at {}:{}", "", file, line, HEX_WIDTH));
if more {
try!(write!(self, " <... and possibly more>"));
}
self.0.write_all(&['\n' as u8]).map_err(IntoInner::into_inner)
}
w.write_all(&['\n' as u8])
}


@@ -188,10 +179,9 @@ pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> {
#[cfg(test)]
mod tests {
use prelude::v1::*;
use sys_common;
macro_rules! t { ($a:expr, $b:expr) => ({
let mut m = Vec::new();
sys_common::backtrace::demangle(&mut m, $a).unwrap();
super::demangle(&mut m, $a).unwrap();
assert_eq!(String::from_utf8(m).unwrap(), $b);
}) }

@@ -0,0 +1,30 @@
// Copyright 2013 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.

#![doc(hidden)]

//! Runtime services
//!
//! The `rt` module provides a narrow set of runtime services,
//! including the global heap (exported in `heap`) and unwinding and
//! backtrace support. The APIs in this module are highly unstable,
//! and should be considered as private implementation details for the
//! time being.

mod panicking;
mod backtrace;
mod at_exit;

pub use self::at_exit::at_exit;
pub use self::panicking::{LOCAL_STDERR, rust_std_on_panic};

pub fn cleanup() {
at_exit::cleanup();
}
@@ -10,15 +10,18 @@

use prelude::v1::*;
use io::prelude::*;
use sys::unwind::prelude::*;
use sys::backtrace::prelude::*;
use sys::stdio::prelude as stdio;
use super::backtrace::BacktraceOutput as Output;

use any::Any;
use cell::Cell;
use cell::RefCell;
use sync::StaticMutex;
use intrinsics;
use sys::stdio::Stderr;
use sys_common::backtrace;
use sys_common::thread_info;
use sys_common::util;
use thread;
use io;

thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }

@@ -28,6 +31,9 @@ thread_local! {
}
}

static BACKTRACE_LOCK: StaticMutex = StaticMutex::new();
static mut BACKTRACE: Backtrace = Backtrace::new();

fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
log_backtrace: bool) {
let msg = match obj.downcast_ref::<&'static str>() {
@@ -37,62 +43,61 @@ fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
None => "Box<Any>",
}
};
let mut err = Stderr::new().ok();
let thread = thread_info::current_thread();
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
let thread = thread::current();
let name = thread.name().unwrap_or("<unnamed>");

let write = |err: &mut ::io::Write| {
let write = |err: &mut Write| {
let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
name, msg, file, line);
if log_backtrace {
let _ = backtrace::write(err);
let _g = BACKTRACE_LOCK.lock();
let _ = unsafe { BACKTRACE.write(&mut Output(err)) };
}
};

let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
match (prev, err.as_mut()) {
(Some(mut stderr), _) => {
write(&mut *stderr);
let mut s = Some(stderr);
LOCAL_STDERR.with(|slot| {
*slot.borrow_mut() = s.take();
});
}
(None, Some(ref mut err)) => { write(err) }
_ => {}
if let Some(mut w) = LOCAL_STDERR.with(|s| s.borrow_mut().take()) {
write(&mut *w);
LOCAL_STDERR.with(move |slot| {
*slot.borrow_mut() = Some(w);
});
} else {
write(&mut io::stderr())
}
}

pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
let panics = PANIC_COUNT.with(|s| {
let count = s.get() + 1;
s.set(count);
count
});
#[no_mangle]
pub extern fn rust_std_on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
let panics = Unwind::panic_inc();

// If this is the third nested call, on_panic triggered the last panic,
// otherwise the double-panic check would have aborted the process.
// Even if it is likely that on_panic was unable to log the backtrace,
// abort immediately to avoid infinite recursion, so that attaching a
// debugger provides a useable stacktrace.
if panics >= 3 {
util::dumb_print(format_args!("thread panicked while processing \
if panics > 1 {
stdio::dumb_print(format_args!("thread panicked while processing \
panic. aborting."));
unsafe { intrinsics::abort() }
}

// If this is a double panic, make sure that we print a backtrace
// for this panic. Otherwise only print it if logging is enabled.
let log_backtrace = panics >= 2 || backtrace::log_enabled();
let log_backtrace = panics > 0 || Backtrace::log_enabled();
log_panic(obj, file, line, log_backtrace);

if panics >= 2 {
if panics > 0 {
// If a thread panics while it's already unwinding then we
// have limited options. Currently our preference is to
// just abort. In the future we may consider resuming
// unwinding or otherwise exiting the thread cleanly.
util::dumb_print(format_args!("thread panicked while panicking. \
aborting."));
stdio::dumb_print(format_args!("thread panicked while panicking. \
aborting."));
unsafe { intrinsics::abort() }
}
}

#[no_mangle]
pub extern fn rust_std_report_overflow() {
stdio::dumb_print(format_args!("\nthread '{}' has overflowed its stack",
thread::current().name().unwrap_or("<unknown>")));
}
@@ -10,12 +10,13 @@

use prelude::v1::*;

use sys::sync::traits::*;
use sys::sync::prelude as sys;

use sys::time::prelude::*;
use sync::atomic::{AtomicUsize, Ordering};
use sync::{mutex, MutexGuard, PoisonError};
use sys_common::condvar as sys;
use sys_common::mutex as sys_mutex;
use sys_common::poison::{self, LockResult};
use sys::time::SteadyTime;
use sync::poison::{self, LockResult};
use time::Duration;

/// A type indicating whether a timed wait on a condition variable returned
@@ -229,7 +230,7 @@ impl Condvar {
///
/// To wake up all threads, see `notify_all()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
pub fn notify_one(&self) { unsafe { sys::Condvar::notify_one(&self.inner.inner) } }

/// Wakes up all blocked threads on this condvar.
///
@@ -239,13 +240,13 @@ impl Condvar {
///
/// To wake up only one thread, see `notify_one()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
pub fn notify_all(&self) { unsafe { sys::Condvar::notify_all(&self.inner.inner) } }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Drop for Condvar {
fn drop(&mut self) {
unsafe { self.inner.inner.destroy() }
unsafe { sys::Condvar::destroy(&self.inner.inner) }
}
}

@@ -273,7 +274,7 @@ impl StaticCondvar {
let poisoned = unsafe {
let lock = mutex::guard_lock(&guard);
self.verify(lock);
self.inner.wait(lock);
sys::Condvar::wait(&self.inner, &lock);
mutex::guard_poison(&guard).get()
};
if poisoned {
@@ -315,7 +316,7 @@ impl StaticCondvar {
let (poisoned, result) = unsafe {
let lock = mutex::guard_lock(&guard);
self.verify(lock);
let success = self.inner.wait_timeout(lock, timeout);
let success = sys::Condvar::wait_timeout(&self.inner, lock, timeout);
(mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
};
if poisoned {
@@ -343,14 +344,14 @@ impl StaticCondvar {
where F: FnMut(LockResult<&mut T>) -> bool {
// This could be made more efficient by pushing the implementation into
// sys::condvar
let start = SteadyTime::now();
let start = SteadyTime::now().unwrap();
let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard);
while !f(guard_result
.as_mut()
.map(|g| &mut **g)
.map_err(|e| PoisonError::new(&mut **e.get_mut()))) {
let now = SteadyTime::now();
let consumed = &now - &start;
let now = SteadyTime::now().unwrap();
let consumed = now.delta(&start);
let guard = guard_result.unwrap_or_else(|e| e.into_inner());
let (new_guard_result, timed_out) = if consumed > dur {
(Ok(guard), WaitTimeoutResult(true))
@@ -383,15 +384,15 @@ impl StaticCondvar {
#[unstable(feature = "static_condvar",
reason = "may be merged with Condvar in the future",
issue = "27717")]
pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
pub fn notify_one(&'static self) { unsafe { sys::Condvar::notify_one(&self.inner) } }

/// Wakes up all blocked threads on this condvar.
///
/// See `Condvar::notify_all`.
#[unstable(feature = "static_condvar",
reason = "may be merged with Condvar in the future",
issue = "27717")]
pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
pub fn notify_all(&'static self) { unsafe { sys::Condvar::notify_all(&self.inner) } }

/// Deallocates all resources associated with this static condvar.
///
@@ -403,10 +404,10 @@ impl StaticCondvar {
reason = "may be merged with Condvar in the future",
issue = "27717")]
pub unsafe fn destroy(&'static self) {
self.inner.destroy()
sys::Condvar::destroy(&self.inner)
}

fn verify(&self, mutex: &sys_mutex::Mutex) {
fn verify(&self, mutex: &sys::Mutex) {
let addr = mutex as *const _ as usize;
match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
// If we got out 0, then we have successfully bound the mutex to
@@ -19,13 +19,13 @@

pub use alloc::arc::{Arc, Weak};
pub use core::sync::atomic;

pub use self::barrier::{Barrier, BarrierWaitResult};
pub use self::condvar::{Condvar, StaticCondvar, WaitTimeoutResult, CONDVAR_INIT};
pub use self::mutex::MUTEX_INIT;
pub use self::mutex::{Mutex, MutexGuard, StaticMutex};
pub use self::remutex::{ReentrantMutex, ReentrantMutexGuard};
pub use self::once::{Once, ONCE_INIT};
pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
pub use self::semaphore::{Semaphore, SemaphoreGuard};
@@ -35,6 +35,8 @@ pub mod mpsc;
mod barrier;
mod condvar;
mod mutex;
mod remutex;
mod once;
mod poison;
mod rwlock;
mod semaphore;
@@ -10,12 +10,14 @@

use prelude::v1::*;

use sys::sync::traits::*;
use sys::sync::prelude as sys;

use cell::UnsafeCell;
use fmt;
use marker;
use ops::{Deref, DerefMut};
use sys_common::mutex as sys;
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
use sync::poison::{self, TryLockError, TryLockResult, LockResult};

/// A mutual exclusion primitive useful for protecting shared data
///
@@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use sys::unwind::prelude::*;
use cell::Cell;
use error::{Error};
use fmt;
use marker::Reflect;
use thread;

pub struct Flag { failed: Cell<bool> }

@@ -28,7 +28,7 @@ impl Flag {

#[inline]
pub fn borrow(&self) -> LockResult<Guard> {
let ret = Guard { panicking: thread::panicking() };
let ret = Guard { panicking: Unwind::is_panicking() };
if self.get() {
Err(PoisonError::new(ret))
} else {
@@ -38,7 +38,7 @@ impl Flag {

#[inline]
pub fn done(&self, guard: &Guard) {
if !guard.panicking && thread::panicking() {
if !guard.panicking && Unwind::is_panicking() {
self.failed.set(true);
}
}
@@ -13,11 +13,13 @@

use prelude::v1::*;

use sys::sync::prelude as sys;
use sys::sync::traits::*;

use fmt;
use marker;
use ops::Deref;
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
use sys::mutex as sys;
use sync::poison::{self, TryLockError, TryLockResult, LockResult};

/// A re-entrant mutual exclusion
///
@@ -62,7 +64,7 @@ impl<T> ReentrantMutex<T> {
pub fn new(t: T) -> ReentrantMutex<T> {
unsafe {
let mut mutex = ReentrantMutex {
inner: box sys::ReentrantMutex::uninitialized(),
inner: Box::new(sys::ReentrantMutex::uninitialized()),
poison: poison::Flag::new(),
data: t,
};
@@ -164,7 +166,7 @@ impl<'a, T> Drop for ReentrantMutexGuard<'a, T> {
#[cfg(test)]
mod tests {
use prelude::v1::*;
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use sync::remutex::{ReentrantMutex, ReentrantMutexGuard};
use cell::RefCell;
use sync::Arc;
use boxed;
@@ -10,12 +10,14 @@

use prelude::v1::*;

use sys::sync::traits::*;
use sys::sync::prelude as sys;

use cell::UnsafeCell;
use fmt;
use marker;
use ops::{Deref, DerefMut};
use sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
use sys_common::rwlock as sys;
use sync::poison::{self, LockResult, TryLockError, TryLockResult};

/// A reader-writer lock
///
@@ -101,7 +103,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
reason = "may be merged with RwLock in the future",
issue = "27717")]
pub struct StaticRwLock {
lock: sys::RWLock,
lock: sys::RwLock,
poison: poison::Flag,
}

@@ -293,7 +295,7 @@ impl StaticRwLock {
/// Creates a new rwlock.
pub const fn new() -> StaticRwLock {
StaticRwLock {
lock: sys::RWLock::new(),
lock: sys::RwLock::new(),
poison: poison::Flag::new(),
}
}

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,27 @@
use cell::RefCell;
use thread::Thread;
use thread::LocalKeyState;

thread_local! { static CURRENT_THREAD: RefCell<Option<Thread>> = RefCell::new(None) }

fn with<R, F>(f: F) -> Option<R> where F: FnOnce(&mut Thread) -> R {
if CURRENT_THREAD.state() == LocalKeyState::Destroyed {
return None
}

CURRENT_THREAD.with(move |c| {
let mut c = c.borrow_mut();
if c.is_none() {
*c = Some(Thread::new(None))
}
c.as_mut().map(f)
})
}

pub fn current_thread() -> Option<Thread> {
with(|thread| thread.clone())
}

pub fn set_current_thread(t: Thread) {
CURRENT_THREAD.with(move |c| *c.borrow_mut() = Some(t));
}
@@ -14,9 +14,8 @@

use cell::UnsafeCell;

// Sure wish we had macro hygiene, no?
#[doc(hidden)]
pub use self::imp::Key as __KeyInner;
use sys::thread_local::traits::*;
use sys::thread_local::prelude as sys;

/// A thread local storage key which owns its contents.
///
@@ -69,7 +68,7 @@ pub struct LocalKey<T:'static> {
//
// This is trivially devirtualizable by LLVM because we never store anything
// to this field and rustc can declare the `static` as constant as well.
inner: fn() -> &'static __KeyInner<T>,
inner: fn() -> &'static sys::Key<T>,

// initialization routine to invoke to create a value
init: fn() -> T,
@@ -102,39 +101,23 @@ pub struct LocalKey<T:'static> {
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
#[cfg(not(no_elf_tls))]
macro_rules! thread_local {
(static $name:ident: $t:ty = $init:expr) => (
static $name: $crate::thread::LocalKey<$t> =
__thread_local_inner!($t, $init,
#[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
not(target_arch = "aarch64")),
not(target_arch = "aarch64"), not(no_elf_tls)),
thread_local)]);
);
(pub static $name:ident: $t:ty = $init:expr) => (
pub static $name: $crate::thread::LocalKey<$t> =
__thread_local_inner!($t, $init,
#[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
not(target_arch = "aarch64")),
not(target_arch = "aarch64"), not(no_elf_tls)),
thread_local)]);
);
}

#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
#[cfg(no_elf_tls)]
macro_rules! thread_local {
(static $name:ident: $t:ty = $init:expr) => (
static $name: $crate::thread::LocalKey<$t> =
__thread_local_inner!($t, $init, #[]);
);
(pub static $name:ident: $t:ty = $init:expr) => (
pub static $name: $crate::thread::LocalKey<$t> =
__thread_local_inner!($t, $init, #[]);
);
}

#[doc(hidden)]
#[unstable(feature = "thread_local_internals",
reason = "should not be necessary",
@@ -144,10 +127,10 @@ macro_rules! thread_local {
macro_rules! __thread_local_inner {
($t:ty, $init:expr, #[$($attr:meta),*]) => {{
$(#[$attr])*
static __KEY: $crate::thread::__LocalKeyInner<$t> =
$crate::thread::__LocalKeyInner::new();
static __KEY: $crate::thread::__sys::Key<$t> =
$crate::thread::__sys::Key::new();
fn __init() -> $t { $init }
fn __getit() -> &'static $crate::thread::__LocalKeyInner<$t> { &__KEY }
fn __getit() -> &'static $crate::thread::__sys::Key<$t> { &__KEY }
$crate::thread::LocalKey::new(__getit, __init)
}}
}
@@ -189,7 +172,7 @@ impl<T: 'static> LocalKey<T> {
#[unstable(feature = "thread_local_internals",
reason = "recently added to create a key",
issue = "0")]
pub const fn new(inner: fn() -> &'static __KeyInner<T>,
pub const fn new(inner: fn() -> &'static sys::Key<T>,
init: fn() -> T) -> LocalKey<T> {
LocalKey {
inner: inner,
@@ -212,8 +195,7 @@ impl<T: 'static> LocalKey<T> {
where F: FnOnce(&T) -> R {
let slot = (self.inner)();
unsafe {
let slot = slot.get().expect("cannot access a TLS value during or \
after it is destroyed");
let slot = slot.get().expect("cannot access a TLS value during or after it is destroyed");
f(match *slot.get() {
Some(ref inner) => inner,
None => self.init(slot),
@@ -268,224 +250,6 @@ impl<T: 'static> LocalKey<T> {
}
}

#[cfg(all(any(target_os = "macos", target_os = "linux"),
not(target_arch = "aarch64"),
not(no_elf_tls)))]
#[doc(hidden)]
mod imp {
use cell::{Cell, UnsafeCell};
use intrinsics;
use ptr;

pub struct Key<T> {
inner: UnsafeCell<Option<T>>,

// Metadata to keep track of the state of the destructor. Remember that
// these variables are thread-local, not global.
dtor_registered: Cell<bool>,
dtor_running: Cell<bool>,
}

unsafe impl<T> ::marker::Sync for Key<T> { }

impl<T> Key<T> {
pub const fn new() -> Key<T> {
Key {
inner: UnsafeCell::new(None),
dtor_registered: Cell::new(false),
dtor_running: Cell::new(false)
}
}

pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
Some(&self.inner)
}

unsafe fn register_dtor(&self) {
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
return
}

register_dtor(self as *const _ as *mut u8,
destroy_value::<T>);
self.dtor_registered.set(true);
}
}

// Since what appears to be glibc 2.18 this symbol has been shipped which
// GCC and clang both use to invoke destructors in thread_local globals, so
// let's do the same!
//
// Note, however, that we run on lots older linuxes, as well as cross
// compiling from a newer linux to an older linux, so we also have a
// fallback implementation to use as well.
//
// Due to rust-lang/rust#18804, make sure this is not generic!
#[cfg(target_os = "linux")]
unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
use prelude::v1::*;
use mem;
use libc;
use sys_common::thread_local as os;

extern {
#[linkage = "extern_weak"]
static __dso_handle: *mut u8;
#[linkage = "extern_weak"]
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 libc::c_void, F>(__cxa_thread_atexit_impl)
(dtor, t, &__dso_handle as *const _ as *mut _);
return
}

// The fallback implementation uses a vanilla OS-based TLS key to track
// the list of destructors that need to be run for this thread. The key
// then has its own destructor which runs all the other destructors.
//
// The destructor for DTORS is a little special in that it has a `while`
// loop to continuously drain the list of registered destructors. It
// *should* be the case that this loop always terminates because we
// provide the guarantee that a TLS key cannot be set after it is
// flagged for destruction.
static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
if DTORS.get().is_null() {
let v: Box<List> = box Vec::new();
DTORS.set(Box::into_raw(v) as *mut u8);
}
let list: &mut List = &mut *(DTORS.get() as *mut List);
list.push((t, dtor));

unsafe extern fn run_dtors(mut ptr: *mut u8) {
while !ptr.is_null() {
let list: Box<List> = Box::from_raw(ptr as *mut List);
for &(ptr, dtor) in list.iter() {
dtor(ptr);
}
ptr = DTORS.get();
DTORS.set(ptr::null_mut());
}
}
}

// OSX's analog of the above linux function is this _tlv_atexit function.
// The disassembly of thread_local globals in C++ (at least produced by
// clang) will have this show up in the output.
#[cfg(target_os = "macos")]
unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
extern {
fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
arg: *mut u8);
}
_tlv_atexit(dtor, t);
}

pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
let ptr = ptr as *mut Key<T>;
// Right before we run the user destructor be sure to flag the
// destructor as running for this thread so calls to `get` will return
// `None`.
(*ptr).dtor_running.set(true);

// 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());
}
}
}

#[cfg(any(not(any(target_os = "macos", target_os = "linux")),
target_arch = "aarch64",
no_elf_tls))]
#[doc(hidden)]
mod imp {
use prelude::v1::*;

use cell::{Cell, UnsafeCell};
use marker;
use ptr;
use sys_common::thread_local::StaticKey as OsStaticKey;

pub struct Key<T> {
// OS-TLS key that we'll use to key off.
os: OsStaticKey,
marker: marker::PhantomData<Cell<T>>,
}

unsafe impl<T> ::marker::Sync for Key<T> { }

struct Value<T: 'static> {
key: &'static Key<T>,
value: UnsafeCell<Option<T>>,
}

impl<T: 'static> Key<T> {
pub const fn new() -> Key<T> {
Key {
os: OsStaticKey::new(Some(destroy_value::<T>)),
marker: marker::PhantomData
}
}

pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
let ptr = self.os.get() as *mut Value<T>;
if !ptr.is_null() {
if ptr as usize == 1 {
return None
}
return Some(&(*ptr).value);
}

// If the lookup returned null, we haven't initialized our own local
// copy, so do that now.
let ptr: Box<Value<T>> = box Value {
key: self,
value: UnsafeCell::new(None),
};
let ptr = Box::into_raw(ptr);
self.os.set(ptr as *mut u8);
Some(&(*ptr).value)
}
}

pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
// The OS TLS ensures that this key contains a NULL value when this
// destructor starts to run. We set it back to a sentinel value of 1 to
// ensure that any future calls to `get` for this thread will return
// `None`.
//
// Note that to prevent an infinite loop we reset it back to null right
// before we return from the destructor ourselves.
let ptr = Box::from_raw(ptr as *mut Value<T>);
let key = ptr.key;
key.os.set(1 as *mut u8);
drop(ptr);
key.os.set(ptr::null_mut());
}
}

#[cfg(test)]
mod tests {
use prelude::v1::*;
@@ -161,23 +161,21 @@
#![stable(feature = "rust1", since = "1.0.0")]

use prelude::v1::*;
use sys::rt::prelude::*;
use sys::thread::traits::*;
use sys::unwind::prelude::*;
use sys::thread::prelude as sys;

use alloc::boxed::FnBox;
use any::Any;
use cell::UnsafeCell;
use fmt;
use mem;
use io;
use sync::{Mutex, Condvar, Arc};
use sys::thread as imp;
use sys_common::thread_info;
use sys_common::unwind;
use sys_common::util;
use time::Duration;

////////////////////////////////////////////////////////////////////////////////
// Thread-local storage
////////////////////////////////////////////////////////////////////////////////

mod start;
#[macro_use] mod local;
#[macro_use] mod scoped_tls;

@@ -190,9 +188,12 @@ pub use self::local::{LocalKey, LocalKeyState};
issue = "27715")]
pub use self::scoped_tls::ScopedKey;

#[doc(hidden)] pub use self::local::__KeyInner as __LocalKeyInner;
// Sure wish we had macro hygiene, no?
#[doc(hidden)] pub use sys::thread_local::prelude as __sys;
#[doc(hidden)] pub use self::scoped_tls::__KeyInner as __ScopedKeyInner;

mod info;

////////////////////////////////////////////////////////////////////////////////
// Builder
////////////////////////////////////////////////////////////////////////////////
@@ -250,18 +251,18 @@ impl Builder {
F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
{
unsafe {
self.spawn_inner(Box::new(f)).map(JoinHandle)
self.spawn_inner(f).map(JoinHandle)
}
}

// NB: this function is unsafe as the lifetime parameter of the code to run
// in the new thread is not tied into the return value, and the return
// value must not outlast that lifetime.
unsafe fn spawn_inner<'a, T: Send>(self, f: Box<FnBox() -> T + Send + 'a>)
unsafe fn spawn_inner<'a, T: Send, F: FnOnce() -> T + Send + 'a>(self, f: F)
-> io::Result<JoinInner<T>> {
let Builder { name, stack_size } = self;

let stack_size = stack_size.unwrap_or(util::min_stack());
let stack_size = stack_size.unwrap_or(Runtime::min_stack());

let my_thread = Thread::new(name);
let their_thread = my_thread.clone();
@@ -270,23 +271,33 @@ impl Builder {
= Arc::new(UnsafeCell::new(None));
let their_packet = my_packet.clone();

let main = move || {
if let Some(name) = their_thread.name() {
imp::Thread::set_name(name);
unsafe extern fn main<F: FnOnce()>(data: usize) -> usize {
let f = Box::from_raw(mem::transmute::<_, *mut F>(data));
Runtime::run_thread(*f);
0
}

let run = move || {
if let Some(ref name) = their_thread.name() {
sys::Thread::set_name(name).unwrap();
}
thread_info::set(imp::guard::current(), their_thread);
info::set_current_thread(their_thread);
let mut output = None;
let try_result = {
let ptr = &mut output;
unwind::try(move || *ptr = Some(f()))
Unwind::try(move || *ptr = Some(f()))
};
*their_packet.get() = Some(try_result.map(|()| {
output.unwrap()
}));
};

fn main_addr<F: FnOnce()>(_: &F) -> unsafe extern fn(usize) -> usize {
main::<F>
}

Ok(JoinInner {
native: Some(try!(imp::Thread::new(stack_size, Box::new(main)))),
native: Some(try!(sys::Thread::new(stack_size, main_addr(&run), Box::into_raw(Box::new(run)) as usize))),
thread: my_thread,
packet: Packet(my_packet),
})
@@ -321,22 +332,22 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
/// Gets a handle to the thread that invokes it.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn current() -> Thread {
thread_info::current_thread().expect("use of std::thread::current() is not \
info::current_thread().expect("use of std::thread::current() is not \
possible after the thread's local \
data has been destroyed")
}

/// Cooperatively gives up a timeslice to the OS scheduler.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn yield_now() {
imp::Thread::yield_now()
sys::Thread::yield_()
}

/// Determines whether the current thread is unwinding because of panic.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn panicking() -> bool {
unwind::panicking()
Unwind::is_panicking()
}

/// Invokes a closure, capturing the cause of panic if one occurs.
@@ -385,7 +396,7 @@ pub fn catch_panic<F, R>(f: F) -> Result<R>
let mut result = None;
unsafe {
let result = &mut result;
try!(unwind::try(move || *result = Some(f())))
try!(Unwind::try(move || *result = Some(f())))
}
Ok(result.unwrap())
}
@@ -414,7 +425,7 @@ pub fn sleep_ms(ms: u32) {
/// granularity of time they can sleep for.
#[stable(feature = "thread_sleep", since = "1.4.0")]
pub fn sleep(dur: Duration) {
imp::Thread::sleep(dur)
sys::Thread::sleep(dur).unwrap()
}

/// Blocks unless or until the current thread's token is made available.
@@ -549,11 +560,6 @@ impl fmt::Debug for Thread {
}
}

// a hack to get around privacy restrictions
impl thread_info::NewThread for Thread {
fn new(name: Option<String>) -> Thread { Thread::new(name) }
}

////////////////////////////////////////////////////////////////////////////////
// JoinHandle
////////////////////////////////////////////////////////////////////////////////
@@ -583,14 +589,14 @@ unsafe impl<T: Sync> Sync for Packet<T> {}

/// Inner representation for JoinHandle
struct JoinInner<T> {
native: Option<imp::Thread>,
native: Option<sys::Thread>,
thread: Thread,
packet: Packet<T>,
}

impl<T> JoinInner<T> {
fn join(&mut self) -> Result<T> {
self.native.take().unwrap().join();
try!(self.native.take().unwrap().join().map_err(|b| Box::new(b) as Box<Any + Send + 'static>));
unsafe {
(*self.packet.0.get()).take().unwrap()
}
@@ -83,25 +83,9 @@ macro_rules! scoped_thread_local {
reason = "should not be necessary")]
#[macro_export]
#[allow_internal_unstable]
#[cfg(no_elf_tls)]
macro_rules! __scoped_thread_local_inner {
($t:ty) => {{
static _KEY: $crate::thread::__ScopedKeyInner<$t> =
$crate::thread::__ScopedKeyInner::new();
fn _getit() -> &'static $crate::thread::__ScopedKeyInner<$t> { &_KEY }
$crate::thread::ScopedKey::new(_getit)
}}
}

#[doc(hidden)]
#[unstable(feature = "thread_local_internals",
reason = "should not be necessary")]
#[macro_export]
#[allow_internal_unstable]
#[cfg(not(no_elf_tls))]
macro_rules! __scoped_thread_local_inner {
($t:ty) => {{
#[cfg_attr(not(any(windows,
#[cfg_attr(not(any(windows, not(no_elf_tls),
target_os = "android",
target_os = "ios",
target_os = "netbsd",
Oops, something went wrong.