diff --git a/src/libgreen/simple.rs b/src/libgreen/simple.rs index ddacc11fd9edd..4a0523fe47a7a 100644 --- a/src/libgreen/simple.rs +++ b/src/libgreen/simple.rs @@ -75,7 +75,7 @@ impl Runtime for SimpleTask { fail!() } fn local_io<'a>(&'a mut self) -> Option> { None } - fn stack_bounds(&self) -> Option<(uint, uint)> { None } + fn stack_bounds(&self) -> (uint, uint) { fail!() } fn wrap(~self) -> ~Any { fail!() } } diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs index 183fe8d055528..e1db24e11e472 100644 --- a/src/libgreen/task.rs +++ b/src/libgreen/task.rs @@ -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 } diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index 9c30e94194dd2..d4447fb7f2137 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -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); + + // XXX: this should not exist here #[cfg(stage0)] #[lang = "start"] @@ -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(); } diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 5a1ef5c836e16..73ad5618e3a9d 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -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; } @@ -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), } } @@ -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; @@ -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 { @@ -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 diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 050caef86ebdb..95e39872b7476 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -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>; - 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; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 3efa979e51515..6fb1d11101556 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -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() } }