Skip to content

Commit 9fd687b

Browse files
committed
Only box the function once when creating threads.
1 parent 0c4d81f commit 9fd687b

File tree

5 files changed

+66
-49
lines changed

5 files changed

+66
-49
lines changed

src/libstd/sys/common/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub mod net;
3838
pub mod poison;
3939
pub mod remutex;
4040
pub mod rwlock;
41-
pub mod thread;
4241
pub mod thread_info;
4342
pub mod thread_local;
4443
pub mod unwind;

src/libstd/sys/common/thread.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/libstd/sys/unix/thread.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
use prelude::v1::*;
1212

13-
use alloc::boxed::FnBox;
1413
use cmp;
1514
#[cfg(not(any(target_env = "newlib", target_os = "solaris")))]
1615
use ffi::CString;
@@ -19,10 +18,9 @@ use libc;
1918
use mem;
2019
use ptr;
2120
use sys::os;
21+
use sys::stack_overflow;
2222
use time::Duration;
2323

24-
use sys_common::thread::*;
25-
2624
pub struct Thread {
2725
id: libc::pthread_t,
2826
}
@@ -33,9 +31,38 @@ unsafe impl Send for Thread {}
3331
unsafe impl Sync for Thread {}
3432

3533
impl Thread {
36-
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
34+
pub unsafe fn new<F: FnOnce()>(stack: usize, p: F)
3735
-> io::Result<Thread> {
36+
37+
extern fn thread_start<F: FnOnce()>(main: *mut libc::c_void)
38+
-> *mut libc::c_void {
39+
unsafe {
40+
let main = Box::from_raw(main as *mut F);
41+
// Next, set up our stack overflow handler which may get triggered if we run
42+
// out of stack.
43+
let _handler = stack_overflow::Handler::new();
44+
45+
// Finally, let's run some code.
46+
main();
47+
}
48+
ptr::null_mut()
49+
}
50+
3851
let p = box p;
52+
53+
match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::<F>) {
54+
Ok(thread) => {
55+
mem::forget(p); // ownership passed to pthread_create
56+
Ok(thread)
57+
}
58+
59+
Err(e) => Err(e),
60+
}
61+
}
62+
63+
unsafe fn new_inner(stack: usize, p: *const libc::c_void,
64+
f: extern fn(*mut libc::c_void) -> *mut libc::c_void)
65+
-> io::Result<Thread> {
3966
let mut native: libc::pthread_t = mem::zeroed();
4067
let mut attr: libc::pthread_attr_t = mem::zeroed();
4168
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -59,20 +86,14 @@ impl Thread {
5986
}
6087
};
6188

62-
let ret = libc::pthread_create(&mut native, &attr, thread_start,
63-
&*p as *const _ as *mut _);
89+
let ret = libc::pthread_create(&mut native, &attr, f,
90+
p as *mut _);
6491
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
6592

66-
return if ret != 0 {
93+
if ret != 0 {
6794
Err(io::Error::from_raw_os_error(ret))
6895
} else {
69-
mem::forget(p); // ownership passed to pthread_create
7096
Ok(Thread { id: native })
71-
};
72-
73-
extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
74-
unsafe { start_thread(main); }
75-
ptr::null_mut()
7697
}
7798
}
7899

src/libstd/sys/windows/thread.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,45 @@ use libc::c_void;
1717
use ptr;
1818
use sys::c;
1919
use sys::handle::Handle;
20-
use sys_common::thread::*;
20+
use sys::stack_overflow;
2121
use time::Duration;
2222

2323
pub struct Thread {
2424
handle: Handle
2525
}
2626

2727
impl Thread {
28-
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
28+
pub unsafe fn new<F: FnOnce()>(stack: usize, p: F)
2929
-> io::Result<Thread> {
30+
extern "system" fn thread_start<F: FnOnce()>(main: *mut c_void)
31+
-> c::DWORD {
32+
unsafe {
33+
let main = Box::from_raw(main as *mut F);
34+
35+
// Next, set up our stack overflow handler which may get triggered if we run
36+
// out of stack.
37+
let _handler = stack_overflow::Handler::new();
38+
39+
// Finally, let's run some code.
40+
main();
41+
}
42+
0
43+
}
44+
3045
let p = box p;
3146

47+
match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::<F>) {
48+
Ok(thread) => {
49+
mem::forget(p); // ownership passed to CreateThread
50+
Ok(thread)
51+
}
52+
Err(e) => Err(e),
53+
}
54+
}
55+
56+
unsafe fn new_inner(stack: usize, p: *const c_void,
57+
f: extern "system" fn(*mut c_void) -> *mut c::DWORD)
58+
-> io::Result<Thread> {
3259
// FIXME On UNIX, we guard against stack sizes that are too small but
3360
// that's because pthreads enforces that stacks are at least
3461
// PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
@@ -37,21 +64,15 @@ impl Thread {
3764
// Round up to the next 64 kB because that's what the NT kernel does,
3865
// might as well make it explicit.
3966
let stack_size = (stack + 0xfffe) & (!0xfffe);
40-
let ret = c::CreateThread(ptr::null_mut(), stack_size,
41-
thread_start, &*p as *const _ as *mut _,
67+
let ret = c::CreateThread(ptr::null_mut(), stack,
68+
f, p as *mut _,
4269
0, ptr::null_mut());
4370

4471
return if ret as usize == 0 {
4572
Err(io::Error::last_os_error())
4673
} else {
47-
mem::forget(p); // ownership passed to CreateThread
4874
Ok(Thread { handle: Handle::new(ret) })
4975
};
50-
51-
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
52-
unsafe { start_thread(main); }
53-
0
54-
}
5576
}
5677

5778
pub fn set_name(_name: &str) {

src/libstd/thread/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ impl Builder {
284284

285285
Ok(JoinHandle(JoinInner {
286286
native: unsafe {
287-
Some(try!(imp::Thread::new(stack_size, Box::new(main))))
287+
Some(try!(imp::Thread::new(stack_size, main)))
288288
},
289289
thread: my_thread,
290290
packet: Packet(my_packet),

0 commit comments

Comments
 (0)