diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs index 16f4f01bf39fe..b086337efb212 100644 --- a/src/libstd/sys/common/thread.rs +++ b/src/libstd/sys/common/thread.rs @@ -11,14 +11,13 @@ use prelude::v1::*; use alloc::boxed::FnBox; -use libc; use sys::stack_overflow; -pub unsafe fn start_thread(main: *mut libc::c_void) { +pub unsafe fn start_thread<'a>(main: Box) { // Next, set up our stack overflow handler which may get triggered if we run // out of stack. let _handler = stack_overflow::Handler::new(); // Finally, let's run some code. - Box::from_raw(main as *mut Box)() + main(); } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 793a2ecae89f1..67b0d0fbb9d31 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -10,7 +10,6 @@ use prelude::v1::*; -use alloc::boxed::FnBox; use cmp; #[cfg(not(any(target_env = "newlib", target_os = "solaris")))] use ffi::CString; @@ -33,9 +32,33 @@ unsafe impl Send for Thread {} unsafe impl Sync for Thread {} impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + pub unsafe fn new(stack: usize, p: F) -> io::Result { + + extern fn thread_start(main: *mut libc::c_void) + -> *mut libc::c_void { + unsafe { + let main = Box::from_raw(main as *mut F); + start_thread(main); + } + ptr::null_mut() + } + let p = box p; + + match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::) { + Ok(thread) => { + mem::forget(p); // ownership passed to pthread_create + Ok(thread) + } + + Err(e) => Err(e), + } + } + + unsafe fn new_inner(stack: usize, p: *const libc::c_void, + f: extern fn(*mut libc::c_void) -> *mut libc::c_void) + -> io::Result { let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -59,20 +82,14 @@ impl Thread { } }; - let ret = libc::pthread_create(&mut native, &attr, thread_start, - &*p as *const _ as *mut _); + let ret = libc::pthread_create(&mut native, &attr, f, + p as *mut _); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); - return if ret != 0 { + if ret != 0 { Err(io::Error::from_raw_os_error(ret)) } else { - mem::forget(p); // ownership passed to pthread_create Ok(Thread { id: native }) - }; - - extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { - unsafe { start_thread(main); } - ptr::null_mut() } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index b18772c0c2438..ce67b8f1087c7 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -25,10 +25,31 @@ pub struct Thread { } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + pub unsafe fn new(stack: usize, p: F) -> io::Result { + extern "system" fn thread_start(main: *mut c_void) + -> c::DWORD { + unsafe { + let main = Box::from_raw(main as *mut F); + start_thread(main); + } + 0 + } + let p = box p; + match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::) { + Ok(thread) => { + mem::forget(p); // ownership passed to CreateThread + Ok(thread) + } + Err(e) => Err(e), + } + } + + unsafe fn new_inner(stack: usize, p: *const c_void, + f: extern "system" fn(*mut c_void) -> c::DWORD) + -> io::Result { // 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 @@ -37,21 +58,15 @@ impl Thread { // Round up to the next 64 kB because that's what the NT kernel does, // might as well make it explicit. let stack_size = (stack + 0xfffe) & (!0xfffe); - let ret = c::CreateThread(ptr::null_mut(), stack_size, - thread_start, &*p as *const _ as *mut _, + let ret = c::CreateThread(ptr::null_mut(), stack, + f, p as *mut _, 0, ptr::null_mut()); return if ret as usize == 0 { Err(io::Error::last_os_error()) } else { - mem::forget(p); // ownership passed to CreateThread Ok(Thread { handle: Handle::new(ret) }) }; - - extern "system" fn thread_start(main: *mut c_void) -> c::DWORD { - unsafe { start_thread(main); } - 0 - } } pub fn set_name(_name: &str) { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 116cd5da2ce7b..41b65c13c869f 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -284,7 +284,7 @@ impl Builder { Ok(JoinHandle(JoinInner { native: unsafe { - Some(try!(imp::Thread::new(stack_size, Box::new(main)))) + Some(try!(imp::Thread::new(stack_size, main))) }, thread: my_thread, packet: Packet(my_packet),