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/thread.rs127
1 files changed, 97 insertions, 30 deletions
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;
 }