about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-04 10:16:51 -0800
committerbors <bors@rust-lang.org>2014-01-04 10:16:51 -0800
commitb432e82515f4cc145cf41bbcb92ff9b874b23afe (patch)
treec94c4b24c628207e0522e458054b573e01fe8f64
parentd86cb6a39fee0d437ab1d4642468257b1f6b11f4 (diff)
parentdcaf10f8de7be79d7ef8aa5e048bf6535108dc16 (diff)
downloadrust-b432e82515f4cc145cf41bbcb92ff9b874b23afe.tar.gz
rust-b432e82515f4cc145cf41bbcb92ff9b874b23afe.zip
auto merge of #11306 : alexcrichton/rust/native-bounds, r=pcwalton
This allows inspection of the current task's bounds regardless of what the
underlying task is.

Closes #11293
-rw-r--r--src/libgreen/simple.rs1
-rw-r--r--src/libgreen/task.rs7
-rw-r--r--src/libnative/task.rs27
-rw-r--r--src/libstd/rt/mod.rs1
-rw-r--r--src/libstd/rt/task.rs7
5 files changed, 38 insertions, 5 deletions
diff --git a/src/libgreen/simple.rs b/src/libgreen/simple.rs
index 4f904ee6e6d..ddacc11fd9e 100644
--- a/src/libgreen/simple.rs
+++ b/src/libgreen/simple.rs
@@ -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!() }
 }
 
diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs
index fc4e1c08ba5..183fe8d0555 100644
--- a/src/libgreen/task.rs
+++ b/src/libgreen/task.rs
@@ -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 }
 }
 
diff --git a/src/libnative/task.rs b/src/libnative/task.rs
index c4d3f651777..661358a64e9 100644
--- a/src/libnative/task.rs
+++ b/src/libnative/task.rs
@@ -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
@@ -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) => {
@@ -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
@@ -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();
     })
@@ -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 {
@@ -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
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 9bd804f7bab..050caef86eb 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -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;
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index ae12f944f9c..41819421be8 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -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 {