Renamed record_stack_bounds for clarity.

For a good measure, implemented target_record_stack_bounds for 32-bit Windows as well.
This commit is contained in:
Vadim Chugunov 2014-08-05 20:53:42 -07:00
parent cd2003ffd8
commit 881bfb1a18
5 changed files with 29 additions and 18 deletions
src

@ -105,11 +105,11 @@ impl Context {
// invalid for the current task. Lucky for us `rust_swap_registers`
// is a C function so we don't have to worry about that!
match in_context.stack_bounds {
Some((lo, hi)) => stack::record_stack_bounds_green(lo, hi),
Some((lo, hi)) => stack::record_rust_managed_stack_bounds(lo, hi),
// If we're going back to one of the original contexts or
// something that's possibly not a "normal task", then reset
// the stack limit to 0 to make morestack never fail
None => stack::record_stack_bounds_green(0, uint::MAX),
None => stack::record_rust_managed_stack_bounds(0, uint::MAX),
}
rust_swap_registers(out_regs, in_regs)
}

@ -137,7 +137,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
task.name = Some(str::Slice("<main>"));
drop(task.run(|| {
unsafe {
rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
rt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
}
exit_code = Some(run(main.take_unwrap()));
}).destroy());

@ -84,7 +84,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
let addr = &something_around_the_top_of_the_stack as *const int;
let my_stack = addr as uint;
unsafe {
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
stack::record_os_managed_stack_bounds(my_stack - stack + 1024, my_stack);
}
let mut ops = ops;
ops.stack_bounds = (my_stack - stack + 1024, my_stack);

@ -124,8 +124,23 @@ extern fn stack_exhausted() {
}
}
// Windows maintains a record of upper and lower stack bounds in the Thread Information
// Block (TIB), and some syscalls do check that addresses which are supposed to be in
// the stack, indeed lie between these two values.
// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
//
// When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
// For OS-managed stacks (libnative), we let the OS manage them for us.
//
// On all other platforms both variants behave identically.
#[inline(always)]
pub unsafe fn record_stack_bounds_green(stack_lo: uint, stack_hi: uint) {
pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
record_sp_limit(stack_lo + RED_ZONE);
}
#[inline(always)]
pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
// When the old runtime had segmented stacks, it used a calculation that was
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
// symbol resolution, llvm function calls, etc. In theory this red zone
@ -138,27 +153,23 @@ pub unsafe fn record_stack_bounds_green(stack_lo: uint, stack_hi: uint) {
return target_record_stack_bounds(stack_lo, stack_hi);
#[cfg(not(windows))] #[cfg(not(target_arch = "x86_64"))] #[inline(always)]
#[cfg(not(windows))] #[inline(always)]
unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
#[cfg(windows, target_arch = "x86")] #[inline(always)]
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
// stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
}
#[cfg(windows, target_arch = "x86_64")] #[inline(always)]
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
// Windows compiles C functions which may check the stack bounds. This
// means that if we want to perform valid FFI on windows, then we need
// to ensure that the stack bounds are what they truly are for this
// task. More info can be found at:
// https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839
//
// stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
}
}
#[inline(always)]
pub unsafe fn record_stack_bounds(stack_lo: uint, _stack_hi: uint) {
record_sp_limit(stack_lo + RED_ZONE);
}
/// Records the current limit of the stack as specified by `end`.
///
/// This is stored in an OS-dependent location, likely inside of the thread

@ -44,7 +44,7 @@ static DEFAULT_STACK_SIZE: uint = 1024 * 1024;
#[no_split_stack]
extern fn thread_start(main: *mut libc::c_void) -> imp::rust_thread_return {
unsafe {
stack::record_stack_bounds(0, uint::MAX);
stack::record_os_managed_stack_bounds(0, uint::MAX);
let f: Box<proc()> = mem::transmute(main);
(*f)();
mem::transmute(0 as imp::rust_thread_return)