From cac133c9a86a4687755aeb44908e3fbb2bb35fc2 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 25 Nov 2014 08:52:10 -0800 Subject: Introduce std::thread Also removes: * `std::task` * `std::rt::task` * `std::rt::thread` Notes for the new API are in a follow-up commit. Closes #18000 --- src/libstd/rt/mod.rs | 35 +++++----- src/libstd/rt/thread.rs | 171 ------------------------------------------------ 2 files changed, 15 insertions(+), 191 deletions(-) delete mode 100644 src/libstd/rt/thread.rs (limited to 'src/libstd/rt') diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 676dbb0b498..eff80b5ab2f 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -53,7 +53,9 @@ use failure; use os; use thunk::Thunk; use kinds::Send; +use thread::Thread; use sys_common; +use sys_common::thread::{mod, NewThread}; // Reexport some of our utilities which are expected by other crates. pub use self::util::{default_sched_threads, min_stack, running_on_valgrind}; @@ -73,8 +75,6 @@ pub mod mutex; pub mod thread; pub mod exclusive; pub mod util; -pub mod local; -pub mod task; pub mod unwind; mod args; @@ -98,8 +98,8 @@ pub fn init(argc: int, argv: *const *const u8) { // Need to propagate the unsafety to `start`. unsafe { args::init(argc, argv); - local_ptr::init(); - thread::init(); + sys::thread::guard::init(); + sys::stack_overflow::init(); unwind::register(failure::on_fail); } } @@ -125,9 +125,6 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { /// 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: *const *const u8, main: Thunk) -> int { use prelude::*; use rt; @@ -143,11 +140,9 @@ pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int { // frames above our current position. let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE; - // When using libgreen, one of the first things that we do is to turn off - // the SIGPIPE signal (set it to ignore). By default, some platforms will - // send a *signal* when a EPIPE error would otherwise be delivered. This - // runtime doesn't install a SIGPIPE handler, causing it to kill the - // program, which isn't exactly what we want! + // By default, some platforms will send a *signal* when a EPIPE error would + // otherwise be delivered. This runtime doesn't install a SIGPIPE handler, + // causing it to kill the program, which isn't exactly what we want! // // Hence, we set SIGPIPE to ignore when the program starts up in order to // prevent this problem. @@ -163,17 +158,18 @@ pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int { init(argc, argv); let mut exit_code = None; - let mut main = Some(main); - let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)), - Some(rt::thread::main_guard_page())); - task.name = Some(str::Slice("
")); - drop(task.run(|| { + + let thread: std::Thread = NewThread::new(Some("
".into_string())); + thread_info::set((my_stack_bottom, my_stack_top), + unsafe { sys::thread::guard::main() }, + thread); + unwind::try(|| { unsafe { sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top); } (main.take().unwrap()).invoke(()); exit_code = Some(os::get_exit_status()); - }).destroy()); + }); unsafe { cleanup(); } // If the exit code wasn't set, then the task block must have panicked. return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE); @@ -207,8 +203,7 @@ pub fn at_exit(f: proc():Send) { /// undefined behavior. pub unsafe fn cleanup() { args::cleanup(); - thread::cleanup(); - local_ptr::cleanup(); + sys::stack_overflow::cleanup(); } // FIXME: these probably shouldn't be public... diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs deleted file mode 100644 index c10338b1bce..00000000000 --- a/src/libstd/rt/thread.rs +++ /dev/null @@ -1,171 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Native os-thread management -//! -//! This modules contains bindings necessary for managing OS-level threads. -//! These functions operate outside of the rust runtime, creating threads -//! which are not used for scheduling in any way. - -#![allow(non_camel_case_types)] - -use core::prelude::*; - -use boxed::Box; -use mem; -use sys::stack_overflow; -use sys::thread as imp; - -pub unsafe fn init() { - imp::guard::init(); - stack_overflow::init(); -} - -pub unsafe fn cleanup() { - stack_overflow::cleanup(); -} - -/// This struct represents a native thread's state. This is used to join on an -/// existing thread created in the join-able state. -pub struct Thread { - native: imp::rust_thread, - joined: bool, - packet: Box>, -} - -static DEFAULT_STACK_SIZE: uint = 1024 * 1024; - -/// Returns the last writable byte of the main thread's stack next to the guard -/// page. Must be called from the main thread. -pub fn main_guard_page() -> uint { - unsafe { - imp::guard::main() - } -} - -/// Returns the last writable byte of the current thread's stack next to the -/// guard page. Must not be called from the main thread. -pub fn current_guard_page() -> uint { - unsafe { - imp::guard::current() - } -} - -// There are two impl blocks b/c if T were specified at the top then it's just a -// pain to specify a type parameter on Thread::spawn (which doesn't need the -// type parameter). -impl Thread<()> { - - /// Starts execution of a new OS thread. - /// - /// This function will not wait for the thread to join, but a handle to the - /// thread will be returned. - /// - /// Note that the handle returned is used to acquire the return value of the - /// procedure `main`. The `join` function will wait for the thread to finish - /// and return the value that `main` generated. - /// - /// Also note that the `Thread` returned will *always* wait for the thread - /// to finish executing. This means that even if `join` is not explicitly - /// called, when the `Thread` falls out of scope its destructor will block - /// waiting for the OS thread. - pub fn start(main: proc():Send -> T) -> Thread { - Thread::start_stack(DEFAULT_STACK_SIZE, main) - } - - /// Performs the same functionality as `start`, but specifies an explicit - /// stack size for the new thread. - pub fn start_stack(stack: uint, main: proc():Send -> T) -> Thread { - - // We need the address of the packet to fill in to be stable so when - // `main` fills it in it's still valid, so allocate an extra box to do - // so. - let packet = box None; - let packet2: *mut Option = unsafe { - *mem::transmute::<&Box>, *const *mut Option>(&packet) - }; - let main = proc() unsafe { *packet2 = Some(main()); }; - let native = unsafe { imp::create(stack, box main) }; - - Thread { - native: native, - joined: false, - packet: packet, - } - } - - /// This will spawn a new thread, but it will not wait for the thread to - /// finish, nor is it possible to wait for the thread to finish. - /// - /// This corresponds to creating threads in the 'detached' state on unix - /// systems. Note that platforms may not keep the main program alive even if - /// there are detached thread still running around. - pub fn spawn(main: proc():Send) { - Thread::spawn_stack(DEFAULT_STACK_SIZE, main) - } - - /// Performs the same functionality as `spawn`, but explicitly specifies a - /// stack size for the new thread. - pub fn spawn_stack(stack: uint, main: proc():Send) { - unsafe { - let handle = imp::create(stack, box main); - imp::detach(handle); - } - } - - /// Relinquishes the CPU slot that this OS-thread is currently using, - /// allowing another thread to run for awhile. - pub fn yield_now() { - unsafe { imp::yield_now(); } - } -} - -impl Thread { - /// Wait for this thread to finish, returning the result of the thread's - /// calculation. - pub fn join(mut self) -> T { - assert!(!self.joined); - unsafe { imp::join(self.native) }; - self.joined = true; - assert!(self.packet.is_some()); - self.packet.take().unwrap() - } -} - -#[unsafe_destructor] -impl Drop for Thread { - fn drop(&mut self) { - // This is required for correctness. If this is not done then the thread - // would fill in a return box which no longer exists. - if !self.joined { - unsafe { imp::join(self.native) }; - } - } -} - -#[cfg(test)] -mod tests { - use super::Thread; - - #[test] - fn smoke() { Thread::start(proc (){}).join(); } - - #[test] - fn data() { assert_eq!(Thread::start(proc () { 1i }).join(), 1); } - - #[test] - fn detached() { Thread::spawn(proc () {}) } - - #[test] - fn small_stacks() { - assert_eq!(42i, Thread::start_stack(0, proc () 42i).join()); - assert_eq!(42i, Thread::start_stack(1, proc () 42i).join()); - } -} -- cgit 1.4.1-3-g733a5