2013-05-19 14:39:46 -07:00
|
|
|
// 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.
|
|
|
|
|
2013-05-19 14:57:47 -07:00
|
|
|
//! Access to a single thread-local pointer.
|
|
|
|
//!
|
2014-05-05 18:56:44 -07:00
|
|
|
//! The runtime will use this for storing Box<Task>.
|
2013-05-19 14:57:47 -07:00
|
|
|
//!
|
2014-04-07 19:01:10 +07:00
|
|
|
//! FIXME: Add runtime checks for usage of inconsistent pointer types.
|
2013-05-19 14:57:47 -07:00
|
|
|
//! and for overwriting an existing pointer.
|
2013-05-19 14:39:46 -07:00
|
|
|
|
2014-03-21 18:05:05 -07:00
|
|
|
#![allow(dead_code)]
|
2013-12-08 02:55:28 -05:00
|
|
|
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use core::prelude::*;
|
|
|
|
|
|
|
|
use core::mem;
|
2014-07-10 14:19:17 -07:00
|
|
|
use alloc::boxed::Box;
|
2013-05-19 14:39:46 -07:00
|
|
|
|
2014-09-28 23:38:24 -07:00
|
|
|
#[cfg(any(windows, // mingw-w32 doesn't like thread_local things
|
|
|
|
target_os = "android", // see #10686
|
|
|
|
target_os = "ios"))]
|
2014-04-15 18:18:08 -07:00
|
|
|
pub use self::native::{init, cleanup, put, take, try_take, unsafe_take, exists,
|
|
|
|
unsafe_borrow, try_unsafe_borrow};
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2014-09-28 23:38:24 -07:00
|
|
|
#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
|
2014-04-15 18:18:08 -07:00
|
|
|
pub use self::compiled::{init, cleanup, put, take, try_take, unsafe_take, exists,
|
|
|
|
unsafe_borrow, try_unsafe_borrow};
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2013-12-03 19:18:58 -08:00
|
|
|
/// Encapsulates a borrowed value. When this value goes out of scope, the
|
|
|
|
/// pointer is returned.
|
|
|
|
pub struct Borrowed<T> {
|
2014-06-25 12:47:34 -07:00
|
|
|
val: *const (),
|
2013-12-03 19:18:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
|
|
|
impl<T> Drop for Borrowed<T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
if self.val.is_null() {
|
|
|
|
rtabort!("Aiee, returning null borrowed object!");
|
|
|
|
}
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let val: Box<T> = mem::transmute(self.val);
|
2013-12-03 19:18:58 -08:00
|
|
|
put::<T>(val);
|
2013-12-18 09:57:58 -08:00
|
|
|
rtassert!(exists());
|
2013-12-03 19:18:58 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-13 14:39:04 -07:00
|
|
|
impl<T> Deref<T> for Borrowed<T> {
|
|
|
|
fn deref<'a>(&'a self) -> &'a T {
|
2014-06-25 12:47:34 -07:00
|
|
|
unsafe { &*(self.val as *const T) }
|
2014-04-13 14:39:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> DerefMut<T> for Borrowed<T> {
|
|
|
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
|
|
|
|
unsafe { &mut *(self.val as *mut T) }
|
2013-12-03 19:18:58 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Borrow the thread-local value from thread-local storage.
|
|
|
|
/// While the value is borrowed it is not available in TLS.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
2013-12-03 19:18:58 -08:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn borrow<T>() -> Borrowed<T> {
|
2014-06-25 12:47:34 -07:00
|
|
|
let val: *const () = mem::transmute(take::<T>());
|
2013-12-03 19:18:58 -08:00
|
|
|
Borrowed {
|
|
|
|
val: val,
|
|
|
|
}
|
2013-11-25 18:08:31 -08:00
|
|
|
}
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Compiled implementation of accessing the runtime local pointer. This is
|
|
|
|
/// implemented using LLVM's thread_local attribute which isn't necessarily
|
|
|
|
/// working on all platforms. This implementation is faster, however, so we use
|
|
|
|
/// it wherever possible.
|
2014-09-28 23:38:24 -07:00
|
|
|
#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
|
2013-11-26 20:23:56 -08:00
|
|
|
pub mod compiled {
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2014-07-10 14:19:17 -07:00
|
|
|
use alloc::boxed::Box;
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use core::mem;
|
2013-11-25 18:27:27 -08:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
#[cfg(test)]
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
pub use realrustrt::shouldnt_be_public::RT_TLS_PTR;
|
2013-11-25 18:27:27 -08:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
#[cfg(not(test))]
|
|
|
|
#[thread_local]
|
2013-12-12 22:27:26 +01:00
|
|
|
pub static mut RT_TLS_PTR: *mut u8 = 0 as *mut u8;
|
2013-05-19 14:57:47 -07:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
pub fn init() {}
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
pub unsafe fn cleanup() {}
|
|
|
|
|
2014-01-21 08:19:35 -08:00
|
|
|
// Rationale for all of these functions being inline(never)
|
|
|
|
//
|
|
|
|
// The #[thread_local] annotation gets propagated all the way through to
|
|
|
|
// LLVM, meaning the global is specially treated by LLVM to lower it to an
|
|
|
|
// efficient sequence of instructions. This also involves dealing with fun
|
|
|
|
// stuff in object files and whatnot. Regardless, it turns out this causes
|
|
|
|
// trouble with green threads and lots of optimizations turned on. The
|
2014-09-02 01:35:58 -04:00
|
|
|
// following case study was done on Linux x86_64, but I would imagine that
|
2014-01-21 08:19:35 -08:00
|
|
|
// other platforms are similar.
|
|
|
|
//
|
2014-09-02 01:35:58 -04:00
|
|
|
// On Linux, the instruction sequence for loading the tls pointer global
|
2014-01-21 08:19:35 -08:00
|
|
|
// looks like:
|
|
|
|
//
|
|
|
|
// mov %fs:0x0, %rax
|
|
|
|
// mov -0x8(%rax), %rbx
|
|
|
|
//
|
|
|
|
// This code leads me to believe that (%fs:0x0) is a table, and then the
|
|
|
|
// table contains the TLS values for the process. Hence, the slot at offset
|
|
|
|
// -0x8 is the task TLS pointer. This leads us to the conclusion that this
|
|
|
|
// table is the actual thread local part of each thread. The kernel sets up
|
|
|
|
// the fs segment selector to point at the right region of memory for each
|
|
|
|
// thread.
|
|
|
|
//
|
|
|
|
// Optimizations lead me to believe that this code is lowered to these
|
|
|
|
// instructions in the LLVM codegen passes, because you'll see code like
|
|
|
|
// this when everything is optimized:
|
|
|
|
//
|
|
|
|
// mov %fs:0x0, %r14
|
|
|
|
// mov -0x8(%r14), %rbx
|
|
|
|
// // do something with %rbx, the rust Task pointer
|
|
|
|
//
|
|
|
|
// ... // <- do more things
|
|
|
|
//
|
|
|
|
// mov -0x8(%r14), %rbx
|
|
|
|
// // do something else with %rbx
|
|
|
|
//
|
|
|
|
// Note that the optimization done here is that the first load is not
|
|
|
|
// duplicated during the lower instructions. This means that the %fs:0x0
|
|
|
|
// memory location is only dereferenced once.
|
|
|
|
//
|
|
|
|
// Normally, this is actually a good thing! With green threads, however,
|
|
|
|
// it's very possible for the code labeled "do more things" to context
|
|
|
|
// switch to another thread. If this happens, then we *must* re-load %fs:0x0
|
|
|
|
// because it's changed (we're on a different thread). If we don't re-load
|
|
|
|
// the table location, then we'll be reading the original thread's TLS
|
|
|
|
// values, not our thread's TLS values.
|
|
|
|
//
|
|
|
|
// Hence, we never inline these functions. By never inlining, we're
|
|
|
|
// guaranteed that loading the table is a local decision which is forced to
|
|
|
|
// *always* happen.
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Give a pointer to thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn put<T>(sched: Box<T>) {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
RT_TLS_PTR = mem::transmute(sched)
|
2013-08-03 17:39:59 -07:00
|
|
|
}
|
2013-05-19 14:57:47 -07:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn take<T>() -> Box<T> {
|
2013-12-12 18:05:37 -08:00
|
|
|
let ptr = RT_TLS_PTR;
|
2013-12-18 09:57:58 -08:00
|
|
|
rtassert!(!ptr.is_null());
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let ptr: Box<T> = mem::transmute(ptr);
|
2013-11-26 20:23:56 -08:00
|
|
|
// can't use `as`, due to type not matching with `cfg(test)`
|
2014-06-27 12:30:25 -07:00
|
|
|
RT_TLS_PTR = mem::transmute(0u);
|
2013-11-26 20:23:56 -08:00
|
|
|
ptr
|
|
|
|
}
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2013-12-30 00:55:27 -08:00
|
|
|
/// Optionally take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn try_take<T>() -> Option<Box<T>> {
|
2013-12-30 00:55:27 -08:00
|
|
|
let ptr = RT_TLS_PTR;
|
|
|
|
if ptr.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let ptr: Box<T> = mem::transmute(ptr);
|
2013-12-30 00:55:27 -08:00
|
|
|
// can't use `as`, due to type not matching with `cfg(test)`
|
2014-06-27 12:30:25 -07:00
|
|
|
RT_TLS_PTR = mem::transmute(0u);
|
2013-12-30 00:55:27 -08:00
|
|
|
Some(ptr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
|
|
|
/// Leaves the old pointer in TLS for speed.
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn unsafe_take<T>() -> Box<T> {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
mem::transmute(RT_TLS_PTR)
|
2013-08-17 17:40:38 -07:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Check whether there is a thread-local pointer installed.
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2013-11-26 20:23:56 -08:00
|
|
|
pub fn exists() -> bool {
|
|
|
|
unsafe {
|
|
|
|
RT_TLS_PTR.is_not_null()
|
|
|
|
}
|
|
|
|
}
|
2013-11-06 01:17:04 -05:00
|
|
|
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2013-11-26 20:23:56 -08:00
|
|
|
pub unsafe fn unsafe_borrow<T>() -> *mut T {
|
|
|
|
if RT_TLS_PTR.is_null() {
|
|
|
|
rtabort!("thread-local pointer is null. bogus!");
|
2013-05-19 14:57:47 -07:00
|
|
|
}
|
2013-11-26 20:23:56 -08:00
|
|
|
RT_TLS_PTR as *mut T
|
2013-05-19 14:57:47 -07:00
|
|
|
}
|
|
|
|
|
2014-01-21 08:19:35 -08:00
|
|
|
#[inline(never)] // see comments above
|
2013-11-26 20:23:56 -08:00
|
|
|
pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
|
|
|
|
if RT_TLS_PTR.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(RT_TLS_PTR as *mut T)
|
|
|
|
}
|
2013-11-06 01:17:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Native implementation of having the runtime thread-local pointer. This
|
|
|
|
/// implementation uses the `thread_local_storage` module to provide a
|
|
|
|
/// thread-local value.
|
|
|
|
pub mod native {
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2014-07-10 14:19:17 -07:00
|
|
|
use alloc::boxed::Box;
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use core::mem;
|
|
|
|
use core::ptr;
|
2014-08-18 08:29:44 -07:00
|
|
|
use thread_local_storage as tls;
|
2013-05-19 14:57:47 -07:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
static mut RT_TLS_KEY: tls::Key = -1;
|
2013-05-19 14:57:47 -07:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Initialize the TLS key. Other ops will fail if this isn't executed
|
|
|
|
/// first.
|
|
|
|
pub fn init() {
|
|
|
|
unsafe {
|
2013-12-28 19:44:52 -08:00
|
|
|
tls::create(&mut RT_TLS_KEY);
|
2013-11-26 20:23:56 -08:00
|
|
|
}
|
|
|
|
}
|
2013-05-19 14:57:47 -07:00
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
pub unsafe fn cleanup() {
|
2013-12-28 19:44:52 -08:00
|
|
|
rtassert!(RT_TLS_KEY != -1);
|
2013-11-26 20:23:56 -08:00
|
|
|
tls::destroy(RT_TLS_KEY);
|
2013-08-12 19:09:46 -07:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Give a pointer to thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
|
|
|
#[inline]
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn put<T>(sched: Box<T>) {
|
2013-11-26 20:23:56 -08:00
|
|
|
let key = tls_key();
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let void_ptr: *mut u8 = mem::transmute(sched);
|
2013-11-26 20:23:56 -08:00
|
|
|
tls::set(key, void_ptr);
|
2013-11-06 01:17:04 -05:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
|
|
|
#[inline]
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn take<T>() -> Box<T> {
|
2013-11-26 20:23:56 -08:00
|
|
|
let key = tls_key();
|
2013-12-12 22:27:26 +01:00
|
|
|
let void_ptr: *mut u8 = tls::get(key);
|
2013-11-26 20:23:56 -08:00
|
|
|
if void_ptr.is_null() {
|
|
|
|
rtabort!("thread-local pointer is null. bogus!");
|
|
|
|
}
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let ptr: Box<T> = mem::transmute(void_ptr);
|
2014-09-14 20:27:36 -07:00
|
|
|
tls::set(key, ptr::null_mut());
|
2013-11-26 20:23:56 -08:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2013-12-30 00:55:27 -08:00
|
|
|
/// Optionally take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
|
|
|
#[inline]
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn try_take<T>() -> Option<Box<T>> {
|
2013-12-30 00:55:27 -08:00
|
|
|
match maybe_tls_key() {
|
|
|
|
Some(key) => {
|
2013-12-12 22:27:26 +01:00
|
|
|
let void_ptr: *mut u8 = tls::get(key);
|
2013-12-30 00:55:27 -08:00
|
|
|
if void_ptr.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let ptr: Box<T> = mem::transmute(void_ptr);
|
2014-09-14 20:27:36 -07:00
|
|
|
tls::set(key, ptr::null_mut());
|
2013-12-30 00:55:27 -08:00
|
|
|
Some(ptr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Take ownership of a pointer from thread-local storage.
|
|
|
|
///
|
|
|
|
/// # Safety note
|
|
|
|
///
|
|
|
|
/// Does not validate the pointer type.
|
|
|
|
/// Leaves the old pointer in TLS for speed.
|
|
|
|
#[inline]
|
2014-05-05 18:56:44 -07:00
|
|
|
pub unsafe fn unsafe_take<T>() -> Box<T> {
|
2013-11-26 20:23:56 -08:00
|
|
|
let key = tls_key();
|
2013-12-12 22:27:26 +01:00
|
|
|
let void_ptr: *mut u8 = tls::get(key);
|
2013-11-26 20:23:56 -08:00
|
|
|
if void_ptr.is_null() {
|
|
|
|
rtabort!("thread-local pointer is null. bogus!");
|
|
|
|
}
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 10:34:51 -07:00
|
|
|
let ptr: Box<T> = mem::transmute(void_ptr);
|
2013-11-26 20:23:56 -08:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check whether there is a thread-local pointer installed.
|
|
|
|
pub fn exists() -> bool {
|
|
|
|
unsafe {
|
|
|
|
match maybe_tls_key() {
|
|
|
|
Some(key) => tls::get(key).is_not_null(),
|
|
|
|
None => false
|
2013-09-25 00:56:18 -07:00
|
|
|
}
|
|
|
|
}
|
2013-05-19 14:57:47 -07:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
/// Borrow a mutable reference to the thread-local value
|
|
|
|
///
|
|
|
|
/// # Safety Note
|
|
|
|
///
|
|
|
|
/// Because this leaves the value in thread-local storage it is possible
|
|
|
|
/// For the Scheduler pointer to be aliased
|
|
|
|
pub unsafe fn unsafe_borrow<T>() -> *mut T {
|
|
|
|
let key = tls_key();
|
|
|
|
let void_ptr = tls::get(key);
|
|
|
|
if void_ptr.is_null() {
|
|
|
|
rtabort!("thread-local pointer is null. bogus!");
|
|
|
|
}
|
|
|
|
void_ptr as *mut T
|
2013-11-06 01:17:04 -05:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
|
|
|
|
match maybe_tls_key() {
|
|
|
|
Some(key) => {
|
|
|
|
let void_ptr = tls::get(key);
|
|
|
|
if void_ptr.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(void_ptr as *mut T)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => None
|
|
|
|
}
|
2013-05-19 14:39:46 -07:00
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
#[inline]
|
|
|
|
fn tls_key() -> tls::Key {
|
|
|
|
match maybe_tls_key() {
|
|
|
|
Some(key) => key,
|
|
|
|
None => rtabort!("runtime tls key not initialized")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[cfg(not(test))]
|
|
|
|
pub fn maybe_tls_key() -> Option<tls::Key> {
|
|
|
|
unsafe {
|
|
|
|
// NB: This is a little racy because, while the key is
|
2014-04-21 00:49:39 -04:00
|
|
|
// initialized under a mutex and it's assumed to be initialized
|
2013-11-26 20:23:56 -08:00
|
|
|
// in the Scheduler ctor by any thread that needs to use it,
|
|
|
|
// we are not accessing the key under a mutex. Threads that
|
|
|
|
// are not using the new Scheduler but still *want to check*
|
|
|
|
// whether they are running under a new Scheduler may see a 0
|
|
|
|
// value here that is in the process of being initialized in
|
|
|
|
// another thread. I think this is fine since the only action
|
|
|
|
// they could take if it was initialized would be to check the
|
|
|
|
// thread-local value and see that it's not set.
|
|
|
|
if RT_TLS_KEY != -1 {
|
|
|
|
return Some(RT_TLS_KEY);
|
|
|
|
} else {
|
|
|
|
return None;
|
|
|
|
}
|
2013-05-19 14:39:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:23:56 -08:00
|
|
|
#[inline] #[cfg(test)]
|
|
|
|
pub fn maybe_tls_key() -> Option<tls::Key> {
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
use realrustrt;
|
2013-11-26 20:23:56 -08:00
|
|
|
unsafe {
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-03 19:11:49 -07:00
|
|
|
mem::transmute(realrustrt::shouldnt_be_public::maybe_tls_key())
|
2013-11-26 20:23:56 -08:00
|
|
|
}
|
|
|
|
}
|
2013-05-19 14:39:46 -07:00
|
|
|
}
|