Add a stack_bounds function to the Runtime trait
This allows inspection of the current task's bounds regardless of what the underlying task is. Closes #11293
This commit is contained in:
@@ -75,6 +75,7 @@ impl Runtime for SimpleTask {
|
|||||||
fail!()
|
fail!()
|
||||||
}
|
}
|
||||||
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
|
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
|
||||||
|
fn stack_bounds(&self) -> Option<(uint, uint)> { None }
|
||||||
fn wrap(~self) -> ~Any { fail!() }
|
fn wrap(~self) -> ~Any { fail!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -450,6 +450,13 @@ 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 wrap(~self) -> ~Any { self as ~Any }
|
fn wrap(~self) -> ~Any { self as ~Any }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,17 @@ use bookeeping;
|
|||||||
/// Creates a new Task which is ready to execute as a 1:1 task.
|
/// Creates a new Task which is ready to execute as a 1:1 task.
|
||||||
pub fn new() -> ~Task {
|
pub fn new() -> ~Task {
|
||||||
let mut task = ~Task::new();
|
let mut task = ~Task::new();
|
||||||
task.put_runtime(~Ops {
|
task.put_runtime(ops() as ~rt::Runtime);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ops() -> ~Ops {
|
||||||
|
~Ops {
|
||||||
lock: unsafe { Mutex::new() },
|
lock: unsafe { Mutex::new() },
|
||||||
awoken: false,
|
awoken: false,
|
||||||
io: io::IoFactory::new(),
|
io: io::IoFactory::new(),
|
||||||
} as ~rt::Runtime);
|
stack_bounds: None,
|
||||||
return task;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns a function with the default configuration
|
/// Spawns a function with the default configuration
|
||||||
@@ -53,7 +58,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
|
|||||||
notify_chan, name, stack_size
|
notify_chan, name, stack_size
|
||||||
} = opts;
|
} = opts;
|
||||||
|
|
||||||
let mut task = new();
|
let mut task = ~Task::new();
|
||||||
task.name = name;
|
task.name = name;
|
||||||
match notify_chan {
|
match notify_chan {
|
||||||
Some(chan) => {
|
Some(chan) => {
|
||||||
@@ -65,6 +70,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
|
|||||||
|
|
||||||
let stack = stack_size.unwrap_or(env::min_stack());
|
let stack = stack_size.unwrap_or(env::min_stack());
|
||||||
let task = task;
|
let task = task;
|
||||||
|
let ops = ops();
|
||||||
|
|
||||||
// Spawning a new OS thread guarantees that __morestack will never get
|
// Spawning a new OS thread guarantees that __morestack will never get
|
||||||
// triggered, but we must manually set up the actual stack bounds once this
|
// triggered, but we must manually set up the actual stack bounds once this
|
||||||
@@ -75,13 +81,17 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
|
|||||||
Thread::spawn_stack(stack, proc() {
|
Thread::spawn_stack(stack, proc() {
|
||||||
let something_around_the_top_of_the_stack = 1;
|
let something_around_the_top_of_the_stack = 1;
|
||||||
let addr = &something_around_the_top_of_the_stack as *int;
|
let addr = &something_around_the_top_of_the_stack as *int;
|
||||||
|
let my_stack = addr as uint;
|
||||||
unsafe {
|
unsafe {
|
||||||
let my_stack = addr as uint;
|
|
||||||
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
|
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
|
||||||
}
|
}
|
||||||
|
let mut ops = ops;
|
||||||
|
ops.stack_bounds = Some((my_stack - stack + 1024, my_stack));
|
||||||
|
|
||||||
bookeeping::increment();
|
bookeeping::increment();
|
||||||
let mut f = Some(f);
|
let mut f = Some(f);
|
||||||
|
let mut task = task;
|
||||||
|
task.put_runtime(ops as ~rt::Runtime);
|
||||||
task.run(|| { f.take_unwrap()() });
|
task.run(|| { f.take_unwrap()() });
|
||||||
bookeeping::decrement();
|
bookeeping::decrement();
|
||||||
})
|
})
|
||||||
@@ -93,6 +103,11 @@ struct Ops {
|
|||||||
lock: Mutex, // native synchronization
|
lock: Mutex, // native synchronization
|
||||||
awoken: bool, // used to prevent spurious wakeups
|
awoken: bool, // used to prevent spurious wakeups
|
||||||
io: io::IoFactory, // local I/O factory
|
io: io::IoFactory, // local I/O factory
|
||||||
|
|
||||||
|
// 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)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rt::Runtime for Ops {
|
impl rt::Runtime for Ops {
|
||||||
@@ -114,6 +129,8 @@ impl rt::Runtime for Ops {
|
|||||||
self as ~Any
|
self as ~Any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stack_bounds(&self) -> Option<(uint, uint)> { self.stack_bounds }
|
||||||
|
|
||||||
// This function gets a little interesting. There are a few safety and
|
// 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
|
// ownership violations going on here, but this is all done in the name of
|
||||||
// shared state. Additionally, all of the violations are protected with a
|
// shared state. Additionally, all of the violations are protected with a
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ pub trait Runtime {
|
|||||||
// you're in.
|
// you're in.
|
||||||
fn spawn_sibling(~self, cur_task: ~Task, opts: TaskOpts, f: proc());
|
fn spawn_sibling(~self, cur_task: ~Task, opts: TaskOpts, f: proc());
|
||||||
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
|
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
|
||||||
|
fn stack_bounds(&self) -> Option<(uint, uint)>; // (lo, hi)
|
||||||
|
|
||||||
// XXX: This is a serious code smell and this should not exist at all.
|
// XXX: This is a serious code smell and this should not exist at all.
|
||||||
fn wrap(~self) -> ~Any;
|
fn wrap(~self) -> ~Any;
|
||||||
|
|||||||
@@ -277,6 +277,13 @@ impl Task {
|
|||||||
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
|
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
|
||||||
self.imp.get_mut_ref().local_io()
|
self.imp.get_mut_ref().local_io()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)> {
|
||||||
|
self.imp.get_ref().stack_bounds()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Task {
|
impl Drop for Task {
|
||||||
|
|||||||
Reference in New Issue
Block a user