Skip to content

Add a stack_bounds function to the Runtime trait #11306

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 4, 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
1 change: 1 addition & 0 deletions src/libgreen/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +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 wrap(~self) -> ~Any { fail!() }
}

Expand Down
7 changes: 7 additions & 0 deletions src/libgreen/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}

Expand Down
27 changes: 22 additions & 5 deletions src/libnative/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ use bookeeping;
/// Creates a new Task which is ready to execute as a 1:1 task.
pub fn new() -> ~Task {
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() },
awoken: false,
io: io::IoFactory::new(),
} as ~rt::Runtime);
return task;
stack_bounds: None,
}
}

/// Spawns a function with the default configuration
Expand All @@ -53,7 +58,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
notify_chan, name, stack_size
} = opts;

let mut task = new();
let mut task = ~Task::new();
task.name = name;
match notify_chan {
Some(chan) => {
Expand All @@ -65,6 +70,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {

let stack = stack_size.unwrap_or(env::min_stack());
let task = task;
let ops = ops();

// Spawning a new OS thread guarantees that __morestack will never get
// triggered, but we must manually set up the actual stack bounds once this
Expand All @@ -75,13 +81,17 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
Thread::spawn_stack(stack, proc() {
let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *int;
let my_stack = addr as uint;
unsafe {
let my_stack = addr as uint;
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();
let mut f = Some(f);
let mut task = task;
task.put_runtime(ops as ~rt::Runtime);
task.run(|| { f.take_unwrap()() });
bookeeping::decrement();
})
Expand All @@ -93,6 +103,11 @@ struct Ops {
lock: Mutex, // native synchronization
awoken: bool, // used to prevent spurious wakeups
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 {
Expand All @@ -114,6 +129,8 @@ impl rt::Runtime for Ops {
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
// 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
Expand Down
1 change: 1 addition & 0 deletions src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ 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)

// XXX: This is a serious code smell and this should not exist at all.
fn wrap(~self) -> ~Any;
Expand Down
7 changes: 7 additions & 0 deletions src/libstd/rt/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ impl Task {
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
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 {
Expand Down