The compiler will no longer inject libgreen as the default runtime for rust programs, this commit switches it over to libnative by default. Now that libnative has baked for some time, it is ready enough to start getting more serious usage as the default runtime for rustc generated binaries. We've found that there isn't really a correct decision in choosing a 1:1 or M:N runtime as a default for all applications, but it seems that a larger number of programs today would work more reasonable with a native default rather than a green default. With this commit come a number of bugfixes: * The main native task is now named "<main>" * The main native task has the stack bounds set up properly * #[no_uv] was renamed to #[no_start] * The core-run-destroy test was rewritten for both libnative and libgreen and one of the tests was modified to be more robust. * The process-detach test was locked to libgreen because it uses signal handling
125 lines
4 KiB
Rust
125 lines
4 KiB
Rust
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! The native I/O and threading crate
|
|
//!
|
|
//! This crate contains an implementation of 1:1 scheduling for a "native"
|
|
//! runtime. In addition, all I/O provided by this crate is the thread blocking
|
|
//! version of I/O.
|
|
//!
|
|
//! # Starting with libnative
|
|
//!
|
|
//! ```rust
|
|
//! extern crate native;
|
|
//!
|
|
//! #[start]
|
|
//! fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }
|
|
//!
|
|
//! fn main() {
|
|
//! // this code is running on the main OS thread
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! # Force spawning a native task
|
|
//!
|
|
//! ```rust
|
|
//! extern crate native;
|
|
//!
|
|
//! fn main() {
|
|
//! // We're not sure whether this main function is run in 1:1 or M:N mode.
|
|
//!
|
|
//! native::task::spawn(proc() {
|
|
//! // this code is guaranteed to be run on a native thread
|
|
//! });
|
|
//! }
|
|
//! ```
|
|
|
|
#[crate_id = "native#0.10-pre"];
|
|
#[license = "MIT/ASL2"];
|
|
#[crate_type = "rlib"];
|
|
#[crate_type = "dylib"];
|
|
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
|
html_root_url = "http://static.rust-lang.org/doc/master")];
|
|
#[deny(unused_result, unused_must_use)];
|
|
#[allow(non_camel_case_types)];
|
|
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0
|
|
|
|
// NB this crate explicitly does *not* allow glob imports, please seriously
|
|
// consider whether they're needed before adding that feature here (the
|
|
// answer is that you don't need them)
|
|
|
|
use std::os;
|
|
use std::rt;
|
|
use std::str;
|
|
|
|
pub mod io;
|
|
pub mod task;
|
|
|
|
#[cfg(windows)]
|
|
#[cfg(android)]
|
|
static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
|
|
#[cfg(unix, not(android))]
|
|
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
|
|
|
|
#[lang = "start"]
|
|
#[cfg(not(test), not(stage0))]
|
|
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
|
|
use std::cast;
|
|
start(argc, argv, proc() {
|
|
let main: extern "Rust" fn() = unsafe { cast::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.
|
|
///
|
|
/// This function will only return once *all* native threads in the system have
|
|
/// exited.
|
|
pub fn start(argc: int, argv: **u8, main: proc()) -> int {
|
|
let something_around_the_top_of_the_stack = 1;
|
|
let addr = &something_around_the_top_of_the_stack as *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;
|
|
|
|
rt::init(argc, argv);
|
|
let mut exit_code = None;
|
|
let mut main = Some(main);
|
|
let mut task = task::new((my_stack_bottom, my_stack_top));
|
|
task.name = Some(str::Slice("<main>"));
|
|
let t = task.run(|| {
|
|
unsafe {
|
|
rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
|
|
}
|
|
exit_code = Some(run(main.take_unwrap()));
|
|
});
|
|
drop(t);
|
|
unsafe { rt::cleanup(); }
|
|
// If the exit code wasn't set, then the task block must have failed.
|
|
return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
|
|
}
|
|
|
|
/// Executes a procedure on the current thread in a Rust task context.
|
|
///
|
|
/// This function has all of the same details as `start` except for a different
|
|
/// number of arguments.
|
|
pub fn run(main: proc()) -> int {
|
|
main();
|
|
os::get_exit_status()
|
|
}
|