We just approximate with a 2MB stack for native::start.
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!() }
}
}
}
- 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 }
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, nativestart)]
#[lang = "start"]
/// 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(); }
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;
}
lock: unsafe { Mutex::new() },
awoken: false,
io: io::IoFactory::new(),
- stack_bounds: None,
+ // these *should* get overwritten
+ stack_bounds: (0, 0),
}
}
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;
// 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 {
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
// 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;
/// 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()
}
}