about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-05 08:56:08 -0800
committerbors <bors@rust-lang.org>2013-11-05 08:56:08 -0800
commit7fb583be7b0df80c91df026c6a2bde550bc27a7c (patch)
tree5471652a73737a511636093172321b7d1dc06130 /src
parent92065ceb634872f53a1a402cf306fbf02550b00d (diff)
parent47e0bd403a04d26506f723ac44ee9ea0aa5d3ad5 (diff)
downloadrust-7fb583be7b0df80c91df026c6a2bde550bc27a7c.tar.gz
rust-7fb583be7b0df80c91df026c6a2bde550bc27a7c.zip
auto merge of #10290 : dbussink/rust/thread_in_rust, r=alexcrichton
This binds to the appropriate pthreads_* and Windows specific functions
and calls them from Rust. This allows for removal of the C++ support
code for threads.

This needs to be reviewed for the Windows parts, I've tested on OS X and Linux.

Fixes #10162
Diffstat (limited to 'src')
-rw-r--r--src/libstd/libc.rs63
-rw-r--r--src/libstd/rt/thread.rs127
-rw-r--r--src/rt/rust_builtin.cpp37
-rw-r--r--src/rt/rustrt.def.in3
-rw-r--r--src/rt/sync/rust_thread.cpp65
-rw-r--r--src/rt/sync/rust_thread.h38
6 files changed, 153 insertions, 180 deletions
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
index f992b327495..9c84f770807 100644
--- a/src/libstd/libc.rs
+++ b/src/libstd/libc.rs
@@ -224,7 +224,10 @@ pub mod types {
         pub mod common {
             pub mod posix01 {
                 use libc::types::common::c95::{c_void};
-                use libc::types::os::arch::c95::{c_char, size_t};
+                use libc::types::os::arch::c95::{c_char, c_ulong, size_t};
+
+                pub type pthread_t = c_ulong;
+
                 pub struct glob_t {
                     gl_pathc: size_t,
                     gl_pathv: **c_char,
@@ -294,7 +297,7 @@ pub mod types {
             }
             #[cfg(target_arch = "x86")]
             pub mod posix01 {
-                use libc::types::os::arch::c95::{c_short, c_long, time_t};
+                use libc::types::os::arch::c95::{c_char, c_short, c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use libc::types::os::arch::posix88::{mode_t, off_t};
                 use libc::types::os::arch::posix88::{uid_t};
@@ -325,10 +328,14 @@ pub mod types {
                     __unused4: c_long,
                     __unused5: c_long,
                 }
+
+                pub struct pthread_attr_t {
+                    __size: [c_char, ..36]
+                }
             }
             #[cfg(target_arch = "arm")]
             pub mod posix01 {
-                use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t};
+                use libc::types::os::arch::c95::{c_char, c_uchar, c_uint, c_ulong, time_t};
                 use libc::types::os::arch::c99::{c_longlong, c_ulonglong};
                 use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t};
 
@@ -357,10 +364,14 @@ pub mod types {
                     st_ctime_nsec: c_ulong,
                     st_ino: c_ulonglong
                 }
+
+                pub struct pthread_attr_t {
+                    __size: [c_char, ..36]
+                }
             }
             #[cfg(target_arch = "mips")]
             pub mod posix01 {
-                use libc::types::os::arch::c95::{c_long, c_ulong, time_t};
+                use libc::types::os::arch::c95::{c_char, c_long, c_ulong, time_t};
                 use libc::types::os::arch::posix88::{gid_t, ino_t};
                 use libc::types::os::arch::posix88::{mode_t, off_t};
                 use libc::types::os::arch::posix88::{uid_t};
@@ -391,6 +402,10 @@ pub mod types {
                     st_blocks: blkcnt_t,
                     st_pad5: [c_long, ..14],
                 }
+
+                pub struct pthread_attr_t {
+                    __size: [c_char, ..36]
+                }
             }
             pub mod posix08 {}
             pub mod bsd44 {}
@@ -435,7 +450,7 @@ pub mod types {
                 pub type ssize_t = i64;
             }
             pub mod posix01 {
-                use libc::types::os::arch::c95::{c_int, c_long, time_t};
+                use libc::types::os::arch::c95::{c_char, c_int, c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use libc::types::os::arch::posix88::{mode_t, off_t};
                 use libc::types::os::arch::posix88::{uid_t};
@@ -463,6 +478,10 @@ pub mod types {
                     st_ctime_nsec: c_long,
                     __unused: [c_long, ..3],
                 }
+
+                pub struct pthread_attr_t {
+                    __size: [c_char, ..56]
+                }
             }
             pub mod posix08 {
             }
@@ -479,6 +498,10 @@ pub mod types {
             pub mod posix01 {
                 use libc::types::common::c95::{c_void};
                 use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                use libc::types::os::arch::c99::{uintptr_t};
+
+                pub type pthread_t = uintptr_t;
+
                 pub struct glob_t {
                     gl_pathc:  size_t,
                     __unused1: size_t,
@@ -535,6 +558,7 @@ pub mod types {
                 pub type ssize_t = i64;
             }
             pub mod posix01 {
+                use libc::types::common::c95::{c_void};
                 use libc::types::common::c99::{uint8_t, uint32_t, int32_t};
                 use libc::types::os::arch::c95::{c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
@@ -569,6 +593,8 @@ pub mod types {
                     st_birthtime_nsec: c_long,
                     __unused: [uint8_t, ..2],
                 }
+
+                pub type pthread_attr_t = *c_void;
             }
             pub mod posix08 {
             }
@@ -945,6 +971,10 @@ pub mod types {
             pub mod posix01 {
                 use libc::types::common::c95::{c_void};
                 use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                use libc::types::os::arch::c99::{uintptr_t};
+
+                pub type pthread_t = uintptr_t;
+
                 pub struct glob_t {
                     gl_pathc:  size_t,
                     __unused1: c_int,
@@ -1002,7 +1032,7 @@ pub mod types {
             }
             pub mod posix01 {
                 use libc::types::common::c99::{int32_t, int64_t, uint32_t};
-                use libc::types::os::arch::c95::{c_long, time_t};
+                use libc::types::os::arch::c95::{c_char, c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t,
                                                      mode_t, off_t, uid_t};
 
@@ -1034,6 +1064,11 @@ pub mod types {
                     st_lspare: int32_t,
                     st_qspare: [int64_t, ..2],
                 }
+
+                pub struct pthread_attr_t {
+                    __sig: c_long,
+                    __opaque: [c_char, ..36]
+                }
             }
             pub mod posix08 {
             }
@@ -1083,7 +1118,7 @@ pub mod types {
             pub mod posix01 {
                 use libc::types::common::c99::{int32_t, int64_t};
                 use libc::types::common::c99::{uint32_t};
-                use libc::types::os::arch::c95::{c_long, time_t};
+                use libc::types::os::arch::c95::{c_char, c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use libc::types::os::arch::posix88::{mode_t, off_t, uid_t};
 
@@ -1115,6 +1150,11 @@ pub mod types {
                     st_lspare: int32_t,
                     st_qspare: [int64_t, ..2],
                 }
+
+                pub struct pthread_attr_t {
+                    __sig: c_long,
+                    __opaque: [c_char, ..56]
+                }
             }
             pub mod posix08 {
             }
@@ -1800,6 +1840,9 @@ pub mod consts {
             pub static _SC_XOPEN_LEGACY : c_int = 129;
             pub static _SC_XOPEN_REALTIME : c_int = 130;
             pub static _SC_XOPEN_REALTIME_THREADS : c_int = 131;
+
+            pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
+            pub static PTHREAD_CREATE_DETACHED: c_int = 1;
         }
         pub mod posix08 {
         }
@@ -2207,6 +2250,9 @@ pub mod consts {
             pub static _SC_XOPEN_UNIX : c_int = 115;
             pub static _SC_XOPEN_VERSION : c_int = 116;
             pub static _SC_XOPEN_XCU_VERSION : c_int = 117;
+
+            pub static PTHREAD_CREATE_JOINABLE: c_int = 0;
+            pub static PTHREAD_CREATE_DETACHED: c_int = 1;
         }
         pub mod posix08 {
         }
@@ -2560,6 +2606,9 @@ pub mod consts {
             pub static _SC_XOPEN_UNIX : c_int = 115;
             pub static _SC_XOPEN_VERSION : c_int = 116;
             pub static _SC_XOPEN_XCU_VERSION : c_int = 121;
+
+            pub static PTHREAD_CREATE_JOINABLE: c_int = 1;
+            pub static PTHREAD_CREATE_DETACHED: c_int = 2;
         }
         pub mod posix08 {
         }
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
index a3731e0b57a..9838a191197 100644
--- a/src/libstd/rt/thread.rs
+++ b/src/libstd/rt/thread.rs
@@ -8,74 +8,141 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(non_camel_case_types)];
+
 use cast;
 use libc;
 use ops::Drop;
-use unstable::raw;
 use uint;
+use ptr;
+
+#[cfg(windows)]
+use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T,
+                                   LPVOID, DWORD, LPDWORD, HANDLE};
 
-#[allow(non_camel_case_types)] // runtime type
-type raw_thread = libc::c_void;
+#[cfg(windows)] type rust_thread = HANDLE;
+#[cfg(unix)] type rust_thread = libc::pthread_t;
 
 pub struct Thread {
-    priv main: ~fn(),
-    priv raw_thread: *raw_thread,
+    priv native: rust_thread,
     priv joined: bool
 }
 
+static DEFAULT_STACK_SIZE: libc::size_t = 1024*1024;
+
+#[cfg(windows)] type rust_thread_return = DWORD;
+#[cfg(unix)] type rust_thread_return = *libc::c_void;
+
 impl Thread {
-    #[fixed_stack_segment] #[inline(never)]
+
     pub fn start(main: ~fn()) -> Thread {
         // 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 re-build the main function
-        // and invoke it from there.
+        // no_split_stack annotation), and then we extract the main function
+        // and invoke it.
         #[no_split_stack]
-        extern "C" fn thread_start(code: *(), env: *()) {
+        extern "C" fn thread_start(trampoline: *libc::c_void) -> rust_thread_return {
             use rt::context;
             unsafe {
                 context::record_stack_bounds(0, uint::max_value);
-                let f: &fn() = cast::transmute(raw::Closure {
-                    code: code,
-                    env: env,
-                });
-                f();
+                let f: ~~fn() = cast::transmute(trampoline);
+                (*f)();
             }
+            unsafe { cast::transmute(0) }
         }
 
-        let raw_thread = unsafe {
-            let c: raw::Closure = cast::transmute_copy(&main);
-            let raw::Closure { code, env } = c;
-            rust_raw_thread_start(thread_start, code, env)
-        };
+        let native = native_thread_create(thread_start, ~main);
         Thread {
-            main: main,
-            raw_thread: raw_thread,
+            native: native,
             joined: false,
         }
     }
 
     pub fn join(mut self) {
-        #[fixed_stack_segment]; #[inline(never)];
-
         assert!(!self.joined);
-        unsafe { rust_raw_thread_join(self.raw_thread); }
+        native_thread_join(self.native);
         self.joined = true;
     }
 }
 
+#[cfg(windows)]
+fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
+                        tramp: ~~fn()) -> rust_thread {
+    #[fixed_stack_segment];
+
+    unsafe {
+        let ptr: *mut libc::c_void = cast::transmute(tramp);
+        CreateThread(ptr::mut_null(), DEFAULT_STACK_SIZE, thread_start, ptr, 0, ptr::mut_null())
+    }
+}
+
+#[cfg(windows)]
+fn native_thread_join(native: rust_thread) {
+    #[fixed_stack_segment];
+    use libc::consts::os::extra::INFINITE;
+    unsafe { WaitForSingleObject(native, INFINITE); }
+}
+
+#[cfg(unix)]
+fn native_thread_create(thread_start: extern "C" fn(*libc::c_void) -> rust_thread_return,
+                        tramp: ~~fn()) -> rust_thread {
+    #[fixed_stack_segment];
+
+    use unstable::intrinsics;
+    let mut native: libc::pthread_t = unsafe { intrinsics::uninit() };
+
+    unsafe {
+        use libc::consts::os::posix01::PTHREAD_CREATE_JOINABLE;
+
+        let mut attr: libc::pthread_attr_t = intrinsics::uninit();
+        assert!(pthread_attr_init(&mut attr) == 0);
+        assert!(pthread_attr_setstacksize(&mut attr, DEFAULT_STACK_SIZE) == 0);
+        assert!(pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE) == 0);
+
+        let ptr: *libc::c_void = cast::transmute(tramp);
+        assert!(pthread_create(&mut native, &attr, thread_start, ptr) == 0);
+    }
+    native
+}
+
+#[cfg(unix)]
+fn native_thread_join(native: rust_thread) {
+    #[fixed_stack_segment];
+    unsafe { assert!(pthread_join(native, ptr::null()) == 0) }
+}
+
 impl Drop for Thread {
     fn drop(&mut self) {
         #[fixed_stack_segment]; #[inline(never)];
-
         assert!(self.joined);
-        unsafe { rust_raw_thread_delete(self.raw_thread) }
     }
 }
 
+#[cfg(windows, target_arch = "x86")]
+extern "stdcall" {
+    fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
+                    lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
+                    lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
+    fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+}
+
+#[cfg(windows, target_arch = "x86_64")]
+extern {
+    fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T,
+                    lpStartAddress: extern "C" fn(*libc::c_void) -> rust_thread_return,
+                    lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE;
+    fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+}
+
+#[cfg(unix)]
 extern {
-    fn rust_raw_thread_start(f: extern "C" fn(*(), *()),
-                             code: *(), env: *()) -> *raw_thread;
-    fn rust_raw_thread_join(thread: *raw_thread);
-    fn rust_raw_thread_delete(thread: *raw_thread);
+    fn pthread_create(native: *mut libc::pthread_t, attr: *libc::pthread_attr_t,
+                      f: extern "C" fn(*libc::c_void) -> rust_thread_return,
+                      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_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;
 }
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 90cfd98bc48..486c95a548d 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -11,7 +11,6 @@
 /* Foreign builtins. */
 
 #include "rust_util.h"
-#include "sync/rust_thread.h"
 #include "sync/lock_and_signal.h"
 #include "vg/valgrind.h"
 
@@ -385,42 +384,6 @@ rust_signal_little_lock(lock_and_signal *lock) {
     lock->signal();
 }
 
-typedef void(startfn)(void*, void*);
-
-class raw_thread: public rust_thread {
-public:
-    startfn *raw_start;
-    void *rust_fn;
-    void *rust_env;
-
-    raw_thread(startfn *raw_start, void *rust_fn, void *rust_env)
-        : raw_start(raw_start), rust_fn(rust_fn), rust_env(rust_env) { }
-
-    virtual void run() {
-        raw_start(rust_fn, rust_env);
-    }
-};
-
-extern "C" raw_thread*
-rust_raw_thread_start(startfn *raw_start, void *rust_start, void *rust_env) {
-    assert(raw_start && rust_start);
-    raw_thread *thread = new raw_thread(raw_start, rust_start, rust_env);
-    thread->start();
-    return thread;
-}
-
-extern "C" void
-rust_raw_thread_join(raw_thread *thread) {
-    assert(thread);
-    thread->join();
-}
-
-extern "C" void
-rust_raw_thread_delete(raw_thread *thread) {
-    assert(thread);
-    delete thread;
-}
-
 #ifndef _WIN32
 #include <sys/types.h>
 #include <dirent.h>
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 275966583d9..3b581e94be7 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -42,9 +42,6 @@ rust_signal_little_lock
 rust_wait_little_lock
 tdefl_compress_mem_to_heap
 tinfl_decompress_mem_to_heap
-rust_raw_thread_start
-rust_raw_thread_join
-rust_raw_thread_delete
 swap_registers
 rust_readdir
 rust_opendir
diff --git a/src/rt/sync/rust_thread.cpp b/src/rt/sync/rust_thread.cpp
deleted file mode 100644
index 7223d187137..00000000000
--- a/src/rt/sync/rust_thread.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2012 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.
-
-
-#include "rust_thread.h"
-#include <limits.h>
-
-const size_t default_stack_sz = 1024*1024;
-
-rust_thread::rust_thread() : thread(0) {
-}
-
-rust_thread::~rust_thread() {
-}
-
-#if defined(__WIN32__)
-static DWORD WINAPI
-#elif defined(__GNUC__)
-static void *
-#else
-#error "Platform not supported"
-#endif
-rust_thread_start(void *ptr) {
-    rust_thread *thread = (rust_thread *) ptr;
-    thread->run();
-    return 0;
-}
-
-void
-rust_thread::start() {
-#if defined(__WIN32__)
-   thread = CreateThread(NULL, default_stack_sz, rust_thread_start, this, 0, NULL);
-#else
-   // PTHREAD_STACK_MIN of some system is larger than default size
-   // so we check stack_sz to prevent assertion failure.
-   size_t stack_sz = default_stack_sz;
-   if (stack_sz < PTHREAD_STACK_MIN) {
-      stack_sz = PTHREAD_STACK_MIN;
-   }
-   pthread_attr_t attr;
-   CHECKED(pthread_attr_init(&attr));
-   CHECKED(pthread_attr_setstacksize(&attr, stack_sz));
-   CHECKED(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
-   CHECKED(pthread_create(&thread, &attr, rust_thread_start, (void *) this));
-#endif
-}
-
-void
-rust_thread::join() {
-#if defined(__WIN32__)
-   if (thread)
-     WaitForSingleObject(thread, INFINITE);
-#else
-   if (thread)
-     CHECKED(pthread_join(thread, NULL));
-#endif
-   thread = 0;
-}
diff --git a/src/rt/sync/rust_thread.h b/src/rt/sync/rust_thread.h
deleted file mode 100644
index 257eefceb43..00000000000
--- a/src/rt/sync/rust_thread.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012 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.
-
-#ifndef RUST_THREAD_H
-#define RUST_THREAD_H
-
-#include "rust_globals.h"
-
-/**
- * Thread utility class. Derive and implement your own run() method.
- */
-class rust_thread {
- private:
-#if defined(__WIN32__)
-    HANDLE thread;
-#else
-    pthread_t thread;
-#endif
- public:
-
-    rust_thread();
-    virtual ~rust_thread();
-
-    void start();
-
-    virtual void run() = 0;
-
-    void join();
-};
-
-#endif /* RUST_THREAD_H */