core: Add a scheduler mode, osmain, to spawn onto the main scheduler
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -96,3 +96,4 @@ rust_dbg_lock_unlock
|
||||
rust_dbg_lock_wait
|
||||
rust_dbg_lock_signal
|
||||
rust_dbg_call
|
||||
rust_osmain_sched_id
|
||||
|
||||
46
src/test/run-pass/osmain.rs
Normal file
46
src/test/run-pass/osmain.rs
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user