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:
parent
cd2003ffd8
commit
881bfb1a18
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user