Skip to content

Commit dcaf10f

Browse files
committed
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
1 parent a1cb8dc commit dcaf10f

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

src/libgreen/simple.rs

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl Runtime for SimpleTask {
7575
fail!()
7676
}
7777
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
78+
fn stack_bounds(&self) -> Option<(uint, uint)> { None }
7879
fn wrap(~self) -> ~Any { fail!() }
7980
}
8081

src/libgreen/task.rs

+7
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,13 @@ impl Runtime for GreenTask {
450450
}
451451
}
452452

453+
fn stack_bounds(&self) -> Option<(uint, uint)> {
454+
self.coroutine.as_ref().map(|c| {
455+
(c.current_stack_segment.start() as uint,
456+
c.current_stack_segment.end() as uint)
457+
})
458+
}
459+
453460
fn wrap(~self) -> ~Any { self as ~Any }
454461
}
455462

src/libnative/task.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,17 @@ use bookeeping;
3232
/// Creates a new Task which is ready to execute as a 1:1 task.
3333
pub fn new() -> ~Task {
3434
let mut task = ~Task::new();
35-
task.put_runtime(~Ops {
35+
task.put_runtime(ops() as ~rt::Runtime);
36+
return task;
37+
}
38+
39+
fn ops() -> ~Ops {
40+
~Ops {
3641
lock: unsafe { Mutex::new() },
3742
awoken: false,
3843
io: io::IoFactory::new(),
39-
} as ~rt::Runtime);
40-
return task;
44+
stack_bounds: None,
45+
}
4146
}
4247

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

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

6671
let stack = stack_size.unwrap_or(env::min_stack());
6772
let task = task;
73+
let ops = ops();
6874

6975
// Spawning a new OS thread guarantees that __morestack will never get
7076
// 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()) {
7581
Thread::spawn_stack(stack, proc() {
7682
let something_around_the_top_of_the_stack = 1;
7783
let addr = &something_around_the_top_of_the_stack as *int;
84+
let my_stack = addr as uint;
7885
unsafe {
79-
let my_stack = addr as uint;
8086
stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
8187
}
88+
let mut ops = ops;
89+
ops.stack_bounds = Some((my_stack - stack + 1024, my_stack));
8290

8391
bookeeping::increment();
8492
let mut f = Some(f);
93+
let mut task = task;
94+
task.put_runtime(ops as ~rt::Runtime);
8595
task.run(|| { f.take_unwrap()() });
8696
bookeeping::decrement();
8797
})
@@ -93,6 +103,11 @@ struct Ops {
93103
lock: Mutex, // native synchronization
94104
awoken: bool, // used to prevent spurious wakeups
95105
io: io::IoFactory, // local I/O factory
106+
107+
// This field holds the known bounds of the stack in (lo, hi) form. Not all
108+
// native tasks necessarily know their precise bounds, hence this is
109+
// optional.
110+
stack_bounds: Option<(uint, uint)>,
96111
}
97112

98113
impl rt::Runtime for Ops {
@@ -114,6 +129,8 @@ impl rt::Runtime for Ops {
114129
self as ~Any
115130
}
116131

132+
fn stack_bounds(&self) -> Option<(uint, uint)> { self.stack_bounds }
133+
117134
// This function gets a little interesting. There are a few safety and
118135
// ownership violations going on here, but this is all done in the name of
119136
// shared state. Additionally, all of the violations are protected with a

src/libstd/rt/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ pub trait Runtime {
159159
// you're in.
160160
fn spawn_sibling(~self, cur_task: ~Task, opts: TaskOpts, f: proc());
161161
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
162+
fn stack_bounds(&self) -> Option<(uint, uint)>; // (lo, hi)
162163

163164
// XXX: This is a serious code smell and this should not exist at all.
164165
fn wrap(~self) -> ~Any;

src/libstd/rt/task.rs

+7
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,13 @@ impl Task {
277277
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
278278
self.imp.get_mut_ref().local_io()
279279
}
280+
281+
/// Returns the stack bounds for this task in (lo, hi) format. The stack
282+
/// bounds may not be known for all tasks, so the return value may be
283+
/// `None`.
284+
pub fn stack_bounds(&self) -> Option<(uint, uint)> {
285+
self.imp.get_ref().stack_bounds()
286+
}
280287
}
281288

282289
impl Drop for Task {

0 commit comments

Comments
 (0)