about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-04-03 14:03:27 -0700
committerBrian Anderson <banderson@mozilla.com>2012-04-03 14:28:30 -0700
commitbef72447e75b7e37f43d3a82ce40e419c7f747d2 (patch)
tree92e5355f9320194ca9cb512b1079f73ca89de2c7
parente1858882a49bf0666d4ffb3f45989ac9dbe9c843 (diff)
downloadrust-bef72447e75b7e37f43d3a82ce40e419c7f747d2.tar.gz
rust-bef72447e75b7e37f43d3a82ce40e419c7f747d2.zip
core: Add a scheduler mode, osmain, to spawn onto the main scheduler
-rw-r--r--src/libcore/task.rs37
-rw-r--r--src/rt/rust_builtin.cpp6
-rw-r--r--src/rt/rust_kernel.h2
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/run-pass/osmain.rs46
5 files changed, 90 insertions, 2 deletions
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
index dcd784fb2a3..cdf50aa4837 100644
--- a/src/libcore/task.rs
+++ b/src/libcore/task.rs
@@ -88,6 +88,13 @@ enum sched_mode {
     thread_per_task,
     #[doc = "Tasks are distributed among a fixed number of OS threads"]
     manual_threads(uint),
+    #[doc = "
+    Tasks are scheduled on the main OS thread
+
+    The main OS thread is the thread used to launch the runtime which,
+    in most cases, is the process's initial thread as created by the OS.
+    "]
+    osmain
 }
 
 #[doc = "
@@ -107,7 +114,7 @@ Scheduler configuration options
 "]
 type sched_opts = {
     mode: sched_mode,
-    native_stack_size: option<uint>,
+    native_stack_size: option<uint>
 };
 
 #[doc = "
@@ -525,9 +532,14 @@ fn spawn_raw(opts: task_opts, +f: fn~()) unsafe {
             }
             threads
           }
+          osmain { 0u /* Won't be used */ }
         };
 
-        let sched_id = rustrt::rust_new_sched(num_threads);
+        let sched_id = if opts.mode != osmain {
+            rustrt::rust_new_sched(num_threads)
+        } else {
+            rustrt::rust_osmain_sched_id()
+        };
         rustrt::rust_new_task_in_sched(sched_id)
     }
 
@@ -553,6 +565,7 @@ native mod rustrt {
 
     fn rust_task_is_unwinding(rt: *rust_task) -> bool;
     fn unsupervise();
+    fn rust_osmain_sched_id() -> sched_id;
 }
 
 
@@ -897,3 +910,23 @@ fn test_avoid_copying_the_body_unsupervise() {
         }
     }
 }
+
+#[test]
+fn test_osmain() {
+    let builder = task_builder();
+    let opts = {
+        sched: some({
+            mode: osmain,
+            native_stack_size: none
+        })
+        with get_opts(builder)
+    };
+    set_opts(builder, opts);
+
+    let po = comm::port();
+    let ch = comm::chan(po);
+    run(builder) {||
+        comm::send(ch, ());
+    }
+    comm::recv(po);
+}
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index aa1f1ce1e6a..f13fd4a110b 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -646,6 +646,12 @@ rust_dbg_call(dbg_callback cb, void *data) {
     return cb(data);
 }
 
+extern "C" CDECL rust_sched_id
+rust_osmain_sched_id() {
+    rust_task *task = rust_sched_loop::get_task();
+    return task->kernel->osmain_sched_id();
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h
index 8c1d33c6a5e..927da963dad 100644
--- a/src/rt/rust_kernel.h
+++ b/src/rt/rust_kernel.h
@@ -93,6 +93,8 @@ public:
     void release_port_id(rust_port_id tid);
 
     void set_exit_status(int code);
+
+    rust_sched_id osmain_sched_id() { return osmain_scheduler; }
 };
 
 #endif /* RUST_KERNEL_H */
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 0bc0fddaca7..c8219e922be 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -96,3 +96,4 @@ rust_dbg_lock_unlock
 rust_dbg_lock_wait
 rust_dbg_lock_signal
 rust_dbg_call
+rust_osmain_sched_id
diff --git a/src/test/run-pass/osmain.rs b/src/test/run-pass/osmain.rs
new file mode 100644
index 00000000000..4112ee561f7
--- /dev/null
+++ b/src/test/run-pass/osmain.rs
@@ -0,0 +1,46 @@
+// Jump back and forth between the OS main thread and a new scheduler.
+// The OS main scheduler should continue to be available and not terminate
+// while it is not in use.
+
+fn main() {
+    run(10);
+}
+
+fn run(i: int) {
+
+    log(debug, i);
+
+    if i == 0 {
+        ret;
+    }
+
+    let builder = task::task_builder();
+    let opts = {
+        sched: some({
+            mode: task::osmain,
+            native_stack_size: none
+        })
+        with task::get_opts(builder)
+    };
+    task::set_opts(builder, opts);
+    task::unsupervise(builder);
+    task::run(builder) {||
+        task::yield();
+        let builder = task::task_builder();
+        let opts = {
+            sched: some({
+                mode: task::single_threaded,
+                native_stack_size: none
+            })
+            with task::get_opts(builder)
+        };
+        task::set_opts(builder, opts);
+        task::unsupervise(builder);
+        task::run(builder) {||
+            task::yield();
+            run(i - 1);
+            task::yield();
+        }
+        task::yield();
+    }
+}