2013-12-12 17:54:53 -08: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.
|
|
|
|
|
|
|
|
//! The native runtime 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.
|
|
|
|
|
2014-01-02 10:24:26 -08:00
|
|
|
#[crate_id = "native#0.9"];
|
2013-12-12 17:54:53 -08:00
|
|
|
#[license = "MIT/ASL2"];
|
|
|
|
#[crate_type = "rlib"];
|
|
|
|
#[crate_type = "dylib"];
|
2014-01-07 20:49:13 -08:00
|
|
|
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
|
|
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
|
|
|
html_root_url = "http://static.rust-lang.org/doc/master")];
|
2013-12-12 17:54:53 -08:00
|
|
|
|
|
|
|
// NB this crate explicitly does *not* allow glob imports, please seriously
|
2013-12-13 00:02:54 -08:00
|
|
|
// consider whether they're needed before adding that feature here (the
|
|
|
|
// answer is that you don't need them)
|
2013-12-12 17:54:53 -08:00
|
|
|
|
|
|
|
use std::os;
|
|
|
|
use std::rt;
|
|
|
|
|
2013-12-30 00:55:27 -08:00
|
|
|
mod bookeeping;
|
2013-12-12 17:54:53 -08:00
|
|
|
pub mod io;
|
|
|
|
pub mod task;
|
|
|
|
|
2014-01-07 13:39:55 +11:00
|
|
|
#[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);
|
|
|
|
|
|
|
|
|
2013-12-12 17:54:53 -08:00
|
|
|
// XXX: this should not exist here
|
2014-01-06 09:26:47 -08:00
|
|
|
#[cfg(stage0, nativestart)]
|
2013-12-12 17:54:53 -08:00
|
|
|
#[lang = "start"]
|
2013-12-13 00:02:54 -08:00
|
|
|
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
|
|
|
|
use std::cast;
|
2013-12-18 09:57:58 -08:00
|
|
|
use std::task;
|
2013-12-12 17:54:53 -08:00
|
|
|
|
2013-12-13 00:02:54 -08:00
|
|
|
do start(argc, argv) {
|
|
|
|
// Instead of invoking main directly on this thread, invoke it on
|
|
|
|
// another spawned thread that we are guaranteed to know the size of the
|
|
|
|
// stack of. Currently, we do not have a method of figuring out the size
|
|
|
|
// of the main thread's stack, so for stack overflow detection to work
|
|
|
|
// we must spawn the task in a subtask which we know the stack size of.
|
2013-12-12 17:54:53 -08:00
|
|
|
let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
|
2013-12-18 09:57:58 -08:00
|
|
|
let mut task = task::task();
|
|
|
|
task.name("<main>");
|
|
|
|
match do task.try { main() } {
|
2013-12-12 17:54:53 -08:00
|
|
|
Ok(()) => { os::set_exit_status(0); }
|
|
|
|
Err(..) => { os::set_exit_status(rt::DEFAULT_ERROR_CODE); }
|
|
|
|
}
|
2013-12-13 00:02:54 -08:00
|
|
|
}
|
|
|
|
}
|
2013-12-12 17:54:53 -08:00
|
|
|
|
2013-12-13 00:02:54 -08:00
|
|
|
/// 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 {
|
2014-01-07 13:39:55 +11:00
|
|
|
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;
|
|
|
|
|
2013-12-13 00:02:54 -08:00
|
|
|
rt::init(argc, argv);
|
2013-12-15 00:42:21 -08:00
|
|
|
let mut exit_code = None;
|
|
|
|
let mut main = Some(main);
|
2014-01-07 13:39:55 +11:00
|
|
|
task::new((my_stack_bottom, my_stack_top)).run(|| {
|
2013-12-15 00:42:21 -08:00
|
|
|
exit_code = Some(run(main.take_unwrap()));
|
|
|
|
});
|
2013-12-12 17:54:53 -08:00
|
|
|
unsafe { rt::cleanup(); }
|
2014-01-04 12:21:46 -08:00
|
|
|
// If the exit code wasn't set, then the task block must have failed.
|
|
|
|
return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
|
2013-12-13 00:02:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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 {
|
2013-12-15 00:42:21 -08:00
|
|
|
main();
|
2013-12-30 00:55:27 -08:00
|
|
|
bookeeping::wait_for_other_tasks();
|
2013-12-12 17:54:53 -08:00
|
|
|
os::get_exit_status()
|
|
|
|
}
|