diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 41c8bc68d2b..dd5831c2917 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -273,6 +273,12 @@ debug_ptrcast(type_desc *from_ty, return ptr; } +extern "C" CDECL void * +debug_get_stk_seg() { + rust_task *task = rust_scheduler::get_task(); + return task->stk; +} + extern "C" CDECL rust_vec* rust_list_files(rust_str *path) { rust_task *task = rust_scheduler::get_task(); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 670dbc3a24a..f202cd1fd67 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -222,7 +222,7 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { // FIXME (1226) - The shim functions generated by rustc contain the // morestack prologue, so we need to let them know they have enough // stack. - //record_sp(0); + record_sp(0); rust_scheduler *sched = task->sched; try { @@ -232,8 +232,8 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { //task->record_stack_limit(); throw; } - //task = rust_scheduler::get_task(); - //task->record_stack_limit(); + task = rust_scheduler::get_task(); + task->record_stack_limit(); } struct rust_new_stack2_args { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index de9079800e2..ba1a9c1403d 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -8,6 +8,7 @@ del_port debug_ptrcast debug_tag debug_tydesc +debug_get_stk_seg do_gc drop_task get_port_id diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs new file mode 100644 index 00000000000..ef1a87aeea6 --- /dev/null +++ b/src/test/run-pass/morestack6.rs @@ -0,0 +1,81 @@ +// xfail-test +// compile-flags:--stack-growth + +// This test attempts to force the dynamic linker to resolve +// external symbols as close to the red zone as possible. + +use std; +import std::task; +import std::rand; + +native mod rustrt { + fn set_min_stack(size: uint); + fn debug_get_stk_seg() -> *u8; + + fn unsupervise(); + fn last_os_error() -> str; + fn rust_getcwd() -> str; + fn refcount(box: @int); + fn do_gc(); + fn pin_task(); + fn unpin_task(); + fn get_task_id(); + fn sched_threads(); + fn rust_get_task(); +} + +fn calllink01() { rustrt::unsupervise(); } +fn calllink02() { rustrt::last_os_error(); } +fn calllink03() { rustrt::rust_getcwd(); } +fn calllink04() { rustrt::refcount(@0); } +fn calllink05() { rustrt::do_gc(); } +fn calllink06() { rustrt::pin_task(); } +fn calllink07() { rustrt::unpin_task(); } +fn calllink08() { rustrt::get_task_id(); } +fn calllink09() { rustrt::sched_threads(); } +fn calllink10() { rustrt::rust_get_task(); } + +fn runtest(&&args:(fn(), u32)) { + let (f, frame_backoff) = args; + runtest2(f, frame_backoff, 0 as *u8); +} + +fn runtest2(f: fn(), frame_backoff: u32, last_stk: *u8) -> u32 { + let curr_stk = rustrt::debug_get_stk_seg(); + if (last_stk != curr_stk && last_stk != 0 as *u8) { + // We switched stacks, go back and try to hit the dynamic linker + frame_backoff + } else { + let frame_backoff = runtest2(f, frame_backoff, curr_stk); + if frame_backoff > 1u32 { + frame_backoff - 1u32 + } else if frame_backoff == 1u32 { + f(); + 0u32 + } else { + 0u32 + } + } +} + +fn main() { + let fns = [ + calllink01, + calllink02, + calllink03, + calllink04, + calllink05, + calllink06, + calllink07, + calllink08, + calllink09, + calllink10 + ]; + let rng = rand::mk_rng(); + for f in fns { + let sz = rng.next() % 256u32 + 256u32; + let frame_backoff = rng.next() % 10u32 + 1u32; + rustrt::set_min_stack(sz as uint); + task::join(task::spawn_joinable((f, frame_backoff), runtest)); + } +} \ No newline at end of file