(index<- ) ./libnative/lib.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Wed Apr 9 17:27:02 2014
1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The native I/O and threading crate
12 //!
13 //! This crate contains an implementation of 1:1 scheduling for a "native"
14 //! runtime. In addition, all I/O provided by this crate is the thread blocking
15 //! version of I/O.
16 //!
17 //! # Starting with libnative
18 //!
19 //! ```rust
20 //! extern crate native;
21 //!
22 //! #[start]
23 //! fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }
24 //!
25 //! fn main() {
26 //! // this code is running on the main OS thread
27 //! }
28 //! ```
29 //!
30 //! # Force spawning a native task
31 //!
32 //! ```rust
33 //! extern crate native;
34 //!
35 //! fn main() {
36 //! // We're not sure whether this main function is run in 1:1 or M:N mode.
37 //!
38 //! native::task::spawn(proc() {
39 //! // this code is guaranteed to be run on a native thread
40 //! });
41 //! }
42 //! ```
43
44 #![crate_id = "native#0.11-pre"]
45 #![license = "MIT/ASL2"]
46 #![crate_type = "rlib"]
47 #![crate_type = "dylib"]
48 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
49 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
50 html_root_url = "http://static.rust-lang.org/doc/master")]
51 #![deny(unused_result, unused_must_use)]
52 #![allow(non_camel_case_types)]
53
54 // NB this crate explicitly does *not* allow glob imports, please seriously
55 // consider whether they're needed before adding that feature here (the
56 // answer is that you don't need them)
57
58 extern crate libc;
59
60 use std::os;
61 use std::rt;
62 use std::str;
63
64 pub mod io;
65 pub mod task;
66
67 #[cfg(windows)]
68 #[cfg(android)]
69 static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
70 #[cfg(unix, not(android))]
71 static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
72
73 #[lang = "start"]
74 #[cfg(not(test))]
75 pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
76 use std::cast;
77 start(argc, argv, proc() {
78 let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
79 main();
80 })
81 }
82
83 /// Executes the given procedure after initializing the runtime with the given
84 /// argc/argv.
85 ///
86 /// This procedure is guaranteed to run on the thread calling this function, but
87 /// the stack bounds for this rust task will *not* be set. Care must be taken
88 /// for this function to not overflow its stack.
89 ///
90 /// This function will only return once *all* native threads in the system have
91 /// exited.
92 pub fn start(argc: int, argv: **u8, main: proc()) -> int {
93 let something_around_the_top_of_the_stack = 1;
94 let addr = &something_around_the_top_of_the_stack as *int;
95 let my_stack_top = addr as uint;
96
97 // FIXME #11359 we just assume that this thread has a stack of a
98 // certain size, and estimate that there's at most 20KB of stack
99 // frames above our current position.
100 let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
101
102 // When using libgreen, one of the first things that we do is to turn off
103 // the SIGPIPE signal (set it to ignore). By default, some platforms will
104 // send a *signal* when a EPIPE error would otherwise be delivered. This
105 // runtime doesn't install a SIGPIPE handler, causing it to kill the
106 // program, which isn't exactly what we want!
107 //
108 // Hence, we set SIGPIPE to ignore when the program starts up in order to
109 // prevent this problem.
110 #[cfg(windows)] fn ignore_sigpipe() {}
111 #[cfg(unix)] fn ignore_sigpipe() {
112 use libc;
113 use libc::funcs::posix01::signal::signal;
114 unsafe {
115 assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
116 }
117 }
118 ignore_sigpipe();
119
120 rt::init(argc, argv);
121 let mut exit_code = None;
122 let mut main = Some(main);
123 let mut task = task::new((my_stack_bottom, my_stack_top));
124 task.name = Some(str::Slice("<main>"));
125 let t = task.run(|| {
126 unsafe {
127 rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
128 }
129 exit_code = Some(run(main.take_unwrap()));
130 });
131 drop(t);
132 unsafe { rt::cleanup(); }
133 // If the exit code wasn't set, then the task block must have failed.
134 return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
135 }
136
137 /// Executes a procedure on the current thread in a Rust task context.
138 ///
139 /// This function has all of the same details as `start` except for a different
140 /// number of arguments.
141 pub fn run(main: proc()) -> int {
142 main();
143 os::get_exit_status()
144 }