rust/src/libstd/rt/mod.rs

217 lines
7.9 KiB
Rust

// 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.
//! Runtime services, including the task scheduler and I/O dispatcher
//!
//! The `rt` module provides the private runtime infrastructure necessary to support core language
//! features like the exchange and local heap, logging, local data and unwinding. It also
//! implements the default task scheduler and task model. Initialization routines are provided for
//! setting up runtime resources in common configurations, including that used by `rustc` when
//! generating executables.
//!
//! It is intended that the features provided by `rt` can be factored in a way such that the core
//! library can be built with different 'profiles' for different use cases, e.g. excluding the task
//! scheduler. A number of runtime features though are critical to the functioning of the language
//! and an implementation must be provided regardless of the execution environment.
//!
//! Of foremost importance is the global exchange heap, in the module `heap`. Very little practical
//! Rust code can be written without access to the global heap. Unlike most of `rt` the global heap
//! is truly a global resource and generally operates independently of the rest of the runtime.
//!
//! All other runtime features are task-local, including the local heap, local storage, logging and
//! the stack unwinder.
//!
//! The relationship between `rt` and the rest of the core library is not entirely clear yet and
//! some modules will be moving into or out of `rt` as development proceeds.
//!
//! Several modules in `core` are clients of `rt`:
//!
//! * `std::task` - The user-facing interface to the Rust task model.
//! * `std::local_data` - The interface to local data.
//! * `std::unstable::lang` - Miscellaneous lang items, some of which rely on `std::rt`.
//! * `std::cleanup` - Local heap destruction.
//! * `std::io` - In the future `std::io` will use an `rt` implementation.
//! * `std::logging`
//! * `std::comm`
#![experimental]
// FIXME: this should not be here.
#![allow(missing_docs)]
#![allow(dead_code)]
use borrow::IntoCow;
use failure;
use os;
use thunk::Thunk;
use kinds::Send;
use thread::Thread;
use sys_common;
use sys_common::thread::{mod, NewThread};
// Reexport some of our utilities which are expected by other crates.
pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
// Reexport some functionality from liballoc.
pub use alloc::heap;
// Simple backtrace functionality (to print on panic)
pub mod backtrace;
// Internals
mod macros;
// These should be refactored/moved/made private over time
pub mod mutex;
pub mod thread;
pub mod exclusive;
pub mod util;
<<<<<<< HEAD
=======
pub mod task;
>>>>>>> Remove rt::{local, local_data, thread_local_storage}
pub mod unwind;
mod args;
mod at_exit_imp;
mod libunwind;
/// The default error code of the rust runtime if the main task panics instead
/// of exiting cleanly.
pub const DEFAULT_ERROR_CODE: int = 101;
/// One-time runtime initialization.
///
/// Initializes global state, including frobbing
/// the crate's logging flags, registering GC
/// metadata, and storing the process arguments.
#[allow(experimental)]
pub fn init(argc: int, argv: *const *const u8) {
// FIXME: Derefing these pointers is not safe.
// Need to propagate the unsafety to `start`.
unsafe {
args::init(argc, argv);
thread::init();
unwind::register(failure::on_fail);
}
}
#[cfg(any(windows, android))]
static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
#[cfg(all(unix, not(android)))]
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
#[cfg(not(test))]
#[lang = "start"]
fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
use mem;
start(argc, argv, Thunk::new(move|| {
let main: extern "Rust" fn() = unsafe { mem::transmute(main) };
main();
}))
}
/// Executes the given procedure after initializing the runtime with the given
/// argc/argv.
///
/// This procedure is guaranteed to run on the thread calling this function, but
/// the stack bounds for this rust task will *not* be set. Care must be taken
/// for this function to not overflow its stack.
pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int {
use prelude::*;
use rt;
use rt::task::Task;
use str;
let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *const int;
let my_stack_top = addr as uint;
// FIXME #11359 we just assume that this thread has a stack of a
// certain size, and estimate that there's at most 20KB of stack
// frames above our current position.
let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
// By default, some platforms will send a *signal* when a EPIPE error would
// otherwise be delivered. This runtime doesn't install a SIGPIPE handler,
// causing it to kill the program, which isn't exactly what we want!
//
// Hence, we set SIGPIPE to ignore when the program starts up in order to
// prevent this problem.
#[cfg(windows)] fn ignore_sigpipe() {}
#[cfg(unix)] fn ignore_sigpipe() {
use libc;
use libc::funcs::posix01::signal::signal;
unsafe {
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
}
}
ignore_sigpipe();
init(argc, argv);
let mut exit_code = None;
let thread: std::Thread = NewThread::new(Some("<main>".into_string()));
thread_info::set((my_stack_bottom, my_stack_top),
unsafe { sys::thread::guard::main() },
thread);
unwind::try(|| {
unsafe {
sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
}
(main.take().unwrap()).invoke(());
exit_code = Some(os::get_exit_status());
});
unsafe { cleanup(); }
// If the exit code wasn't set, then the task block must have panicked.
return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
}
/// Enqueues a procedure to run when the runtime is cleaned up
///
/// The procedure passed to this function will be executed as part of the
/// runtime cleanup phase. For normal rust programs, this means that it will run
/// after all other tasks have exited.
///
/// The procedure is *not* executed with a local `Task` available to it, so
/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
/// This is meant for "bare bones" usage to clean up runtime details, this is
/// not meant as a general-purpose "let's clean everything up" function.
///
/// It is forbidden for procedures to register more `at_exit` handlers when they
/// are running, and doing so will lead to a process abort.
pub fn at_exit(f: proc():Send) {
at_exit_imp::push(f);
}
/// One-time runtime cleanup.
///
/// This function is unsafe because it performs no checks to ensure that the
/// runtime has completely ceased running. It is the responsibility of the
/// caller to ensure that the runtime is entirely shut down and nothing will be
/// poking around at the internal components.
///
/// Invoking cleanup while portions of the runtime are still in use may cause
/// undefined behavior.
pub unsafe fn cleanup() {
args::cleanup();
thread::cleanup();
}
// FIXME: these probably shouldn't be public...
#[doc(hidden)]
pub mod shouldnt_be_public {
#[cfg(not(test))]
pub use super::local_ptr::native::maybe_tls_key;
#[cfg(all(not(windows), not(target_os = "android"), not(target_os = "ios")))]
pub use super::local_ptr::compiled::RT_TLS_PTR;
}