Skip to content

std::rt: require known stack bounds for all tasks. #11360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libgreen/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl Runtime for SimpleTask {
fail!()
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
fn stack_bounds(&self) -> Option<(uint, uint)> { None }
fn stack_bounds(&self) -> (uint, uint) { fail!() }
fn wrap(~self) -> ~Any { fail!() }
}

Expand Down
11 changes: 6 additions & 5 deletions src/libgreen/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,11 +450,12 @@ impl Runtime for GreenTask {
}
}

fn stack_bounds(&self) -> Option<(uint, uint)> {
self.coroutine.as_ref().map(|c| {
(c.current_stack_segment.start() as uint,
c.current_stack_segment.end() as uint)
})
fn stack_bounds(&self) -> (uint, uint) {
let c = self.coroutine.as_ref()
.expect("GreenTask.stack_bounds called without a coroutine");

(c.current_stack_segment.start() as uint,
c.current_stack_segment.end() as uint)
}

fn wrap(~self) -> ~Any { self as ~Any }
Expand Down
18 changes: 17 additions & 1 deletion src/libnative/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ mod bookeeping;
pub mod io;
pub mod task;

#[cfg(windows)]
#[cfg(android)]
static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
#[cfg(unix, not(android))]
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brson fixed; some googling indicates that Android has a 1 MB stack by default too.



// XXX: this should not exist here
#[cfg(stage0)]
#[lang = "start"]
Expand Down Expand Up @@ -66,10 +73,19 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
/// This function will only return once *all* native threads in the system have
/// exited.
pub fn start(argc: int, argv: **u8, main: proc()) -> int {
let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *int;
let my_stack_top = addr as uint;

// FIXME #11359 we just assume that this thread has a stack of a
// certain size, and estimate that there's at most 20KB of stack
// frames above our current position.
let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;

rt::init(argc, argv);
let mut exit_code = None;
let mut main = Some(main);
task::new().run(|| {
task::new((my_stack_bottom, my_stack_top)).run(|| {
exit_code = Some(run(main.take_unwrap()));
});
unsafe { rt::cleanup(); }
Expand Down
15 changes: 9 additions & 6 deletions src/libnative/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ use task;
use bookeeping;

/// Creates a new Task which is ready to execute as a 1:1 task.
pub fn new() -> ~Task {
pub fn new(stack_bounds: (uint, uint)) -> ~Task {
let mut task = ~Task::new();
task.put_runtime(ops() as ~rt::Runtime);
let mut ops = ops();
ops.stack_bounds = stack_bounds;
task.put_runtime(ops as ~rt::Runtime);
return task;
}

Expand All @@ -41,7 +43,8 @@ fn ops() -> ~Ops {
lock: unsafe { Mutex::new() },
awoken: false,
io: io::IoFactory::new(),
stack_bounds: None,
// these *should* get overwritten
stack_bounds: (0, 0),
}
}

Expand Down Expand Up @@ -91,7 +94,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
}
let mut ops = ops;
ops.stack_bounds = Some((my_stack - stack + 1024, my_stack));
ops.stack_bounds = (my_stack - stack + 1024, my_stack);

let mut f = Some(f);
let mut task = task;
Expand All @@ -111,7 +114,7 @@ struct Ops {
// This field holds the known bounds of the stack in (lo, hi) form. Not all
// native tasks necessarily know their precise bounds, hence this is
// optional.
stack_bounds: Option<(uint, uint)>,
stack_bounds: (uint, uint),
}

impl rt::Runtime for Ops {
Expand All @@ -133,7 +136,7 @@ impl rt::Runtime for Ops {
self as ~Any
}

fn stack_bounds(&self) -> Option<(uint, uint)> { self.stack_bounds }
fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds }

// This function gets a little interesting. There are a few safety and
// ownership violations going on here, but this is all done in the name of
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ pub trait Runtime {
// you're in.
fn spawn_sibling(~self, cur_task: ~Task, opts: TaskOpts, f: proc());
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
fn stack_bounds(&self) -> Option<(uint, uint)>; // (lo, hi)
/// The (low, high) edges of the current stack.
fn stack_bounds(&self) -> (uint, uint); // (lo, hi)

// XXX: This is a serious code smell and this should not exist at all.
fn wrap(~self) -> ~Any;
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl Task {
/// Returns the stack bounds for this task in (lo, hi) format. The stack
/// bounds may not be known for all tasks, so the return value may be
/// `None`.
pub fn stack_bounds(&self) -> Option<(uint, uint)> {
pub fn stack_bounds(&self) -> (uint, uint) {
self.imp.get_ref().stack_bounds()
}
}
Expand Down