about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/mod.rs5
-rw-r--r--src/libstd/rt/thread.rs348
2 files changed, 1 insertions, 352 deletions
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index a68a632bc37..66e7059422b 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -63,13 +63,10 @@ pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
 // Reexport functionality from librustrt and other crates underneath the
 // standard library which work together to create the entire runtime.
 pub use alloc::{heap, libc_heap};
-pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio};
+pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio, thread};
 pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
 pub use rustrt::{bookkeeping, at_exit, unwind, DEFAULT_ERROR_CODE, Runtime};
 
-// Bindings to system threading libraries.
-pub mod thread;
-
 // Simple backtrace functionality (to print on failure)
 pub mod backtrace;
 
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
deleted file mode 100644
index 5a077e511c0..00000000000
--- a/src/libstd/rt/thread.rs
+++ /dev/null
@@ -1,348 +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 <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.
-
-//! 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)]
-#![allow(unsigned_negate)]
-
-use kinds::Send;
-use libc;
-use mem;
-use ops::Drop;
-use option::{Option, Some, None};
-use owned::Box;
-use uint;
-
-type StartFn = extern "C" fn(*libc::c_void) -> imp::rust_thread_return;
-
-/// 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<T> {
-    native: imp::rust_thread,
-    joined: bool,
-    packet: Box<Option<T>>,
-}
-
-static DEFAULT_STACK_SIZE: uint = 1024 * 1024;
-
-// This is the starting point of rust os threads. The first thing we do
-// is make sure that we don't trigger __morestack (also why this has a
-// no_split_stack annotation), and then we extract the main function
-// and invoke it.
-#[no_split_stack]
-extern fn thread_start(main: *libc::c_void) -> imp::rust_thread_return {
-    use rt::stack;
-    unsafe {
-        stack::record_stack_bounds(0, uint::MAX);
-        let f: Box<proc()> = mem::transmute(main);
-        (*f)();
-        mem::transmute(0 as imp::rust_thread_return)
-    }
-}
-
-// 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<T: Send>(main: proc():Send -> T) -> Thread<T> {
-        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<T: Send>(stack: uint, main: proc():Send -> T) -> Thread<T> {
-
-        // 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<T> = unsafe {
-            *mem::transmute::<&Box<Option<T>>, **mut Option<T>>(&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<T: Send> Thread<T> {
-    /// 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<T: Send> Drop for Thread<T> {
-    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(windows)]
-mod imp {
-    use mem;
-    use cmp;
-    use kinds::Send;
-    use libc;
-    use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
-                                       LPVOID, DWORD, LPDWORD, HANDLE};
-    use os;
-    use owned::Box;
-    use ptr;
-    use rt::stack::RED_ZONE;
-
-    pub type rust_thread = HANDLE;
-    pub type rust_thread_return = DWORD;
-
-    pub unsafe fn create(stack: uint, p: Box<proc():Send>) -> rust_thread {
-        let arg: *mut libc::c_void = mem::transmute(p);
-        // FIXME On UNIX, we guard against stack sizes that are too small but
-        // that's because pthreads enforces that stacks are at least
-        // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
-        // just that below a certain threshold you can't do anything useful.
-        // That threshold is application and architecture-specific, however.
-        // For now, the only requirement is that it's big enough to hold the
-        // red zone.  Round up to the next 64 kB because that's what the NT
-        // kernel does, might as well make it explicit.  With the current
-        // 20 kB red zone, that makes for a 64 kB minimum stack.
-        let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
-        let ret = CreateThread(ptr::mut_null(), stack_size as libc::size_t,
-                               super::thread_start, arg, 0, ptr::mut_null());
-
-        if ret as uint == 0 {
-            // be sure to not leak the closure
-            let _p: Box<proc():Send> = mem::transmute(arg);
-            fail!("failed to spawn native thread: {}", os::last_os_error());
-        }
-        return ret;
-    }
-
-    pub unsafe fn join(native: rust_thread) {
-        use libc::consts::os::extra::INFINITE;
-        WaitForSingleObject(native, INFINITE);
-    }
-
-    pub unsafe fn detach(native: rust_thread) {
-        assert!(libc::CloseHandle(native) != 0);
-    }
-
-    pub unsafe fn yield_now() {
-        // This function will return 0 if there are no other threads to execute,
-        // but this also means that the yield was useless so this isn't really a
-        // case that needs to be worried about.
-        SwitchToThread();
-    }
-
-    #[allow(non_snake_case_functions)]
-    extern "system" {
-        fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
-                        dwStackSize: SIZE_T,
-                        lpStartAddress: super::StartFn,
-                        lpParameter: LPVOID,
-                        dwCreationFlags: DWORD,
-                        lpThreadId: LPDWORD) -> HANDLE;
-        fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
-        fn SwitchToThread() -> BOOL;
-    }
-}
-
-#[cfg(unix)]
-mod imp {
-    use cmp;
-    use kinds::Send;
-    use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
-    use libc;
-    use mem;
-    use os;
-    use owned::Box;
-    use ptr;
-    use rt::stack::RED_ZONE;
-
-    pub type rust_thread = libc::pthread_t;
-    pub type rust_thread_return = *u8;
-
-    pub unsafe fn create(stack: uint, p: Box<proc():Send>) -> rust_thread {
-        let mut native: libc::pthread_t = mem::zeroed();
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(pthread_attr_init(&mut attr), 0);
-        assert_eq!(pthread_attr_setdetachstate(&mut attr,
-                                               PTHREAD_CREATE_JOINABLE), 0);
-
-        // Reserve room for the red zone, the runtime's stack of last resort.
-        let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
-        match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
-            0 => {
-            },
-            libc::EINVAL => {
-                // EINVAL means |stack_size| is either too small or not a
-                // multiple of the system page size.  Because it's definitely
-                // >= PTHREAD_STACK_MIN, it must be an alignment issue.
-                // Round up to the nearest page and try again.
-                let page_size = os::page_size();
-                let stack_size = (stack_size + page_size - 1) & (-(page_size - 1) - 1);
-                assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
-            },
-            errno => {
-                // This cannot really happen.
-                fail!("pthread_attr_setstacksize() error: {} ({})", os::last_os_error(), errno);
-            },
-        };
-
-        let arg: *libc::c_void = mem::transmute(p);
-        let ret = pthread_create(&mut native, &attr, super::thread_start, arg);
-        assert_eq!(pthread_attr_destroy(&mut attr), 0);
-
-        if ret != 0 {
-            // be sure to not leak the closure
-            let _p: Box<proc():Send> = mem::transmute(arg);
-            fail!("failed to spawn native thread: {}", os::last_os_error());
-        }
-        native
-    }
-
-    pub unsafe fn join(native: rust_thread) {
-        assert_eq!(pthread_join(native, ptr::null()), 0);
-    }
-
-    pub unsafe fn detach(native: rust_thread) {
-        assert_eq!(pthread_detach(native), 0);
-    }
-
-    pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
-
-    // glibc >= 2.15 has a __pthread_get_minstack() function that returns
-    // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
-    // storage.  We need that information to avoid blowing up when a small stack
-    // is created in an application with big thread-local storage requirements.
-    // See #6233 for rationale and details.
-    //
-    // Link weakly to the symbol for compatibility with older versions of glibc.
-    // Assumes that we've been dynamically linked to libpthread but that is
-    // currently always the case.  Note that you need to check that the symbol
-    // is non-null before calling it!
-    #[cfg(target_os = "linux")]
-    fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
-        use ptr::RawPtr;
-        type F = unsafe extern "C" fn(*libc::pthread_attr_t) -> libc::size_t;
-        extern {
-            #[linkage = "extern_weak"]
-            static __pthread_get_minstack: *();
-        }
-        if __pthread_get_minstack.is_null() {
-            PTHREAD_STACK_MIN
-        } else {
-            unsafe { mem::transmute::<*(), F>(__pthread_get_minstack)(attr) }
-        }
-    }
-
-    // __pthread_get_minstack() is marked as weak but extern_weak linkage is
-    // not supported on OS X, hence this kludge...
-    #[cfg(not(target_os = "linux"))]
-    fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
-        PTHREAD_STACK_MIN
-    }
-
-    extern {
-        fn pthread_create(native: *mut libc::pthread_t,
-                          attr: *libc::pthread_attr_t,
-                          f: super::StartFn,
-                          value: *libc::c_void) -> libc::c_int;
-        fn pthread_join(native: libc::pthread_t,
-                        value: **libc::c_void) -> libc::c_int;
-        fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
-        fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
-        fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
-                                     stack_size: libc::size_t) -> libc::c_int;
-        fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
-                                       state: libc::c_int) -> libc::c_int;
-        fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
-        fn sched_yield() -> libc::c_int;
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::Thread;
-
-    #[test]
-    fn smoke() { Thread::start(proc (){}).join(); }
-
-    #[test]
-    fn data() { assert_eq!(Thread::start(proc () { 1 }).join(), 1); }
-
-    #[test]
-    fn detached() { Thread::spawn(proc () {}) }
-
-    #[test]
-    fn small_stacks() {
-        assert_eq!(42, Thread::start_stack(0, proc () 42).join());
-        assert_eq!(42, Thread::start_stack(1, proc () 42).join());
-    }
-}
-