From a393fb32211f66cd33b1b0c6cad1991ebd8fae01 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 13 Feb 2012 23:18:21 -0800 Subject: [PATCH] rt: Maintain stack ptrs correctly when returning from stack switches --- src/rt/rust_task.h | 6 ++++++ src/test/run-pass/crust-call-deep2.rs | 27 +++++++++++++++++++++++ src/test/run-pass/crust-call-scrub.rs | 31 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/test/run-pass/crust-call-deep2.rs create mode 100644 src/test/run-pass/crust-call-scrub.rs diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 109f480f68d..13cede08c72 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -231,6 +231,7 @@ rust_task::call_on_c_stack(void *args, void *fn_ptr) { // Too expensive to check // I(thread, on_rust_stack()); + uintptr_t prev_rust_sp = next_rust_sp; next_rust_sp = get_sp(); bool borrowed_a_c_stack = false; @@ -251,6 +252,8 @@ rust_task::call_on_c_stack(void *args, void *fn_ptr) { if (borrowed_a_c_stack) { return_c_stack(); } + + next_rust_sp = prev_rust_sp; } inline void @@ -259,11 +262,14 @@ rust_task::call_on_rust_stack(void *args, void *fn_ptr) { // I(thread, !on_rust_stack()); I(thread, next_rust_sp); + uintptr_t prev_c_sp = next_c_sp; next_c_sp = get_sp(); uintptr_t sp = sanitize_next_sp(next_rust_sp); __morestack(args, fn_ptr, sp); + + next_c_sp = prev_c_sp; } inline void diff --git a/src/test/run-pass/crust-call-deep2.rs b/src/test/run-pass/crust-call-deep2.rs new file mode 100644 index 00000000000..b20e6c3fd76 --- /dev/null +++ b/src/test/run-pass/crust-call-deep2.rs @@ -0,0 +1,27 @@ +native mod rustrt { + fn rust_dbg_call(cb: *u8, + data: ctypes::uintptr_t) -> ctypes::uintptr_t; +} + +crust fn cb(data: ctypes::uintptr_t) -> ctypes::uintptr_t { + if data == 1u { + data + } else { + count(data - 1u) + 1u + } +} + +fn count(n: uint) -> uint { + #debug("n = %?", n); + rustrt::rust_dbg_call(cb, n) +} + +fn main() { + // Make sure we're on a task with small Rust stacks (main currently + // has a large stack) + task::spawn {|| + let result = count(1000u); + #debug("result = %?", result); + assert result == 1000u; + }; +} \ No newline at end of file diff --git a/src/test/run-pass/crust-call-scrub.rs b/src/test/run-pass/crust-call-scrub.rs new file mode 100644 index 00000000000..f3b01e6b29b --- /dev/null +++ b/src/test/run-pass/crust-call-scrub.rs @@ -0,0 +1,31 @@ +// This time we're testing repeatedly going up and down both stacks to +// make sure the stack pointers are maintained properly in both +// directions + +native mod rustrt { + fn rust_dbg_call(cb: *u8, + data: ctypes::uintptr_t) -> ctypes::uintptr_t; +} + +crust fn cb(data: ctypes::uintptr_t) -> ctypes::uintptr_t { + if data == 1u { + data + } else { + count(data - 1u) + count(data - 1u) + } +} + +fn count(n: uint) -> uint { + #debug("n = %?", n); + rustrt::rust_dbg_call(cb, n) +} + +fn main() { + // Make sure we're on a task with small Rust stacks (main currently + // has a large stack) + task::spawn {|| + let result = count(12u); + #debug("result = %?", result); + assert result == 2048u; + }; +} \ No newline at end of file