Skip to content

Commit bc7519c

Browse files
committed
---
yaml --- r: 101344 b: refs/heads/master c: b02b5cd h: refs/heads/master v: v3
1 parent 01c8185 commit bc7519c

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 464b2e2364919f4555d6f8c5025273afd4277366
2+
refs/heads/master: b02b5cdcf42b4fe6b1e3ebe56ad0cd43fd907489
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 6e7f170fedd3c526a643c0b2d13863acd982be02
55
refs/heads/try: a97642026c18a624ff6ea01075dd9550f8ed07ff

trunk/src/libstd/rt/thread.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,30 @@ impl<T: Send> Drop for Thread<T> {
145145
#[cfg(windows)]
146146
mod imp {
147147
use cast;
148+
use cmp;
148149
use libc;
149150
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
150151
LPVOID, DWORD, LPDWORD, HANDLE};
151152
use ptr;
153+
use unstable::stack::RED_ZONE;
152154

153155
pub type rust_thread = HANDLE;
154156
pub type rust_thread_return = DWORD;
155157

156158
pub unsafe fn create(stack: uint, p: ~proc()) -> rust_thread {
157159
let arg: *mut libc::c_void = cast::transmute(p);
158-
CreateThread(ptr::mut_null(), stack as libc::size_t, super::thread_start,
159-
arg, 0, ptr::mut_null())
160+
// FIXME On UNIX, we guard against stack sizes that are too small but
161+
// that's because pthreads enforces that stacks are at least
162+
// PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
163+
// just that below a certain threshold you can't do anything useful.
164+
// That threshold is application and architecture-specific, however.
165+
// For now, the only requirement is that it's big enough to hold the
166+
// red zone. Round up to the next 64 kB because that's what the NT
167+
// kernel does, might as well make it explicit. With the current
168+
// 20 kB red zone, that makes for a 64 kB minimum stack.
169+
let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
170+
CreateThread(ptr::mut_null(), stack_size as libc::size_t,
171+
super::thread_start, arg, 0, ptr::mut_null())
160172
}
161173

162174
pub unsafe fn join(native: rust_thread) {
@@ -190,10 +202,13 @@ mod imp {
190202
#[cfg(unix)]
191203
mod imp {
192204
use cast;
193-
use libc::consts::os::posix01::PTHREAD_CREATE_JOINABLE;
205+
use cmp;
206+
use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
194207
use libc;
208+
use os;
195209
use ptr;
196210
use unstable::intrinsics;
211+
use unstable::stack::RED_ZONE;
197212

198213
pub type rust_thread = libc::pthread_t;
199214
pub type rust_thread_return = *u8;
@@ -202,11 +217,29 @@ mod imp {
202217
let mut native: libc::pthread_t = intrinsics::uninit();
203218
let mut attr: libc::pthread_attr_t = intrinsics::uninit();
204219
assert_eq!(pthread_attr_init(&mut attr), 0);
205-
assert_eq!(pthread_attr_setstacksize(&mut attr,
206-
stack as libc::size_t), 0);
207220
assert_eq!(pthread_attr_setdetachstate(&mut attr,
208221
PTHREAD_CREATE_JOINABLE), 0);
209222

223+
// Reserve room for the red zone, the runtime's stack of last resort.
224+
let stack_size = cmp::max(stack, RED_ZONE + PTHREAD_STACK_MIN as uint);
225+
match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
226+
0 => {
227+
},
228+
libc::EINVAL => {
229+
// EINVAL means |stack_size| is either too small or not a
230+
// multiple of the system page size. Because it's definitely
231+
// >= PTHREAD_STACK_MIN, it must be an alignment issue.
232+
// Round up to the neareast page and try again.
233+
let page_size = os::page_size();
234+
let stack_size = (stack_size + page_size - 1) & (-(page_size - 1) - 1);
235+
assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
236+
},
237+
errno => {
238+
// This cannot really happen.
239+
fail!("pthread_attr_setstacksize() error: {} ({})", os::last_os_error(), errno);
240+
},
241+
};
242+
210243
let arg: *libc::c_void = cast::transmute(p);
211244
assert_eq!(pthread_create(&mut native, &attr,
212245
super::thread_start, arg), 0);
@@ -262,4 +295,10 @@ mod tests {
262295

263296
#[test]
264297
fn detached() { Thread::spawn(proc () {}) }
298+
299+
#[test]
300+
fn small_stacks() {
301+
assert_eq!(42, Thread::start_stack(0, proc () 42).join());
302+
assert_eq!(42, Thread::start_stack(1, proc () 42).join());
303+
}
265304
}

trunk/src/libstd/unstable/stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//! detection is not guaranteed to continue in the future. Usage of this module
2525
//! is discouraged unless absolutely necessary.
2626
27-
static RED_ZONE: uint = 20 * 1024;
27+
pub static RED_ZONE: uint = 20 * 1024;
2828

2929
/// This function is invoked from rust's current __morestack function. Segmented
3030
/// stacks are currently not enabled as segmented stacks, but rather one giant

0 commit comments

Comments
 (0)