(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 mainextern "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  }