]> git.lizzy.rs Git - rust.git/blob - src/libnative/lib.rs
return &mut T from the arenas, not &T
[rust.git] / src / libnative / lib.rs
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: *const *const u8) -> int {
24 //!     native::start(argc, argv, main)
25 //! }
26 //!
27 //! fn main() {
28 //!     // this code is running on the main OS thread
29 //! }
30 //! ```
31 //!
32 //! # Force spawning a native task
33 //!
34 //! ```rust
35 //! extern crate native;
36 //!
37 //! use std::task::TaskBuilder;
38 //! use native::NativeTaskBuilder;
39 //!
40 //! fn main() {
41 //!     // We're not sure whether this main function is run in 1:1 or M:N mode.
42 //!
43 //!     TaskBuilder::new().native().spawn(proc() {
44 //!         // this code is guaranteed to be run on a native thread
45 //!     });
46 //! }
47 //! ```
48
49 #![crate_name = "native"]
50 #![experimental]
51 #![license = "MIT/ASL2"]
52 #![crate_type = "rlib"]
53 #![crate_type = "dylib"]
54 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
55        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
56        html_root_url = "http://doc.rust-lang.org/nightly/")]
57
58 #![deny(unused_result, unused_must_use)]
59 #![allow(non_camel_case_types)]
60 #![allow(unknown_features)]
61 #![feature(default_type_params, lang_items, slicing_syntax)]
62
63 // NB this crate explicitly does *not* allow glob imports, please seriously
64 //    consider whether they're needed before adding that feature here (the
65 //    answer is that you don't need them)
66 #![feature(macro_rules, unsafe_destructor, default_type_params)]
67
68 extern crate alloc;
69 extern crate libc;
70
71 use std::os;
72 use std::rt;
73 use std::str;
74
75 pub use task::NativeTaskBuilder;
76
77 pub mod io;
78 pub mod task;
79
80 #[cfg(any(windows, android))]
81 static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
82 #[cfg(all(unix, not(android)))]
83 static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
84
85 #[lang = "start"]
86 #[cfg(not(test))]
87 pub fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
88     use std::mem;
89     start(argc, argv, proc() {
90         let main: extern "Rust" fn() = unsafe { mem::transmute(main) };
91         main();
92     })
93 }
94
95 /// Executes the given procedure after initializing the runtime with the given
96 /// argc/argv.
97 ///
98 /// This procedure is guaranteed to run on the thread calling this function, but
99 /// the stack bounds for this rust task will *not* be set. Care must be taken
100 /// for this function to not overflow its stack.
101 ///
102 /// This function will only return once *all* native threads in the system have
103 /// exited.
104 pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
105     let something_around_the_top_of_the_stack = 1;
106     let addr = &something_around_the_top_of_the_stack as *const int;
107     let my_stack_top = addr as uint;
108
109     // FIXME #11359 we just assume that this thread has a stack of a
110     // certain size, and estimate that there's at most 20KB of stack
111     // frames above our current position.
112     let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
113
114     // When using libgreen, one of the first things that we do is to turn off
115     // the SIGPIPE signal (set it to ignore). By default, some platforms will
116     // send a *signal* when a EPIPE error would otherwise be delivered. This
117     // runtime doesn't install a SIGPIPE handler, causing it to kill the
118     // program, which isn't exactly what we want!
119     //
120     // Hence, we set SIGPIPE to ignore when the program starts up in order to
121     // prevent this problem.
122     #[cfg(windows)] fn ignore_sigpipe() {}
123     #[cfg(unix)] fn ignore_sigpipe() {
124         use libc;
125         use libc::funcs::posix01::signal::signal;
126         unsafe {
127             assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
128         }
129     }
130     ignore_sigpipe();
131
132     rt::init(argc, argv);
133     let mut exit_code = None;
134     let mut main = Some(main);
135     let mut task = task::new((my_stack_bottom, my_stack_top),
136                              rt::thread::main_guard_page());
137     task.name = Some(str::Slice("<main>"));
138     drop(task.run(|| {
139         unsafe {
140             rt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
141         }
142         exit_code = Some(run(main.take().unwrap()));
143     }).destroy());
144     unsafe { rt::cleanup(); }
145     // If the exit code wasn't set, then the task block must have failed.
146     return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
147 }
148
149 /// Executes a procedure on the current thread in a Rust task context.
150 ///
151 /// This function has all of the same details as `start` except for a different
152 /// number of arguments.
153 pub fn run(main: proc()) -> int {
154     main();
155     os::get_exit_status()
156 }