Skip to content

Commit 91e3cb2

Browse files
committed
Spawn new tasks onto the primary scheduler by default. rust-lang#3760
1 parent f38e972 commit 91e3cb2

File tree

6 files changed

+145
-89
lines changed

6 files changed

+145
-89
lines changed

src/libcore/task/mod.rs

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use prelude::*;
5252
use ptr;
5353
use result;
5454
use task::local_data_priv::{local_get, local_set};
55-
use task::rt::{task_id, rust_task};
55+
use task::rt::{task_id, sched_id, rust_task};
5656
use task;
5757
use util;
5858
use util::replace;
@@ -62,6 +62,12 @@ pub mod local_data;
6262
pub mod rt;
6363
pub mod spawn;
6464

65+
/// A handle to a scheduler
66+
#[deriving_eq]
67+
pub enum Scheduler {
68+
SchedulerHandle(sched_id)
69+
}
70+
6571
/// A handle to a task
6672
#[deriving_eq]
6773
pub enum Task {
@@ -95,7 +101,21 @@ impl TaskResult : Eq {
95101
}
96102

97103
/// Scheduler modes
104+
#[deriving_eq]
98105
pub enum SchedMode {
106+
/// Run task on the default scheduler
107+
DefaultScheduler,
108+
/// Run task on the current scheduler
109+
CurrentScheduler,
110+
/// Run task on a specific scheduler
111+
ExistingScheduler(Scheduler),
112+
/**
113+
* Tasks are scheduled on the main OS thread
114+
*
115+
* The main OS thread is the thread used to launch the runtime which,
116+
* in most cases, is the process's initial thread as created by the OS.
117+
*/
118+
PlatformThread,
99119
/// All tasks run in the same OS thread
100120
SingleThreaded,
101121
/// Tasks are distributed among available CPUs
@@ -104,53 +124,6 @@ pub enum SchedMode {
104124
ThreadPerTask,
105125
/// Tasks are distributed among a fixed number of OS threads
106126
ManualThreads(uint),
107-
/**
108-
* Tasks are scheduled on the main OS thread
109-
*
110-
* The main OS thread is the thread used to launch the runtime which,
111-
* in most cases, is the process's initial thread as created by the OS.
112-
*/
113-
PlatformThread
114-
}
115-
116-
impl SchedMode : cmp::Eq {
117-
pure fn eq(&self, other: &SchedMode) -> bool {
118-
match (*self) {
119-
SingleThreaded => {
120-
match (*other) {
121-
SingleThreaded => true,
122-
_ => false
123-
}
124-
}
125-
ThreadPerCore => {
126-
match (*other) {
127-
ThreadPerCore => true,
128-
_ => false
129-
}
130-
}
131-
ThreadPerTask => {
132-
match (*other) {
133-
ThreadPerTask => true,
134-
_ => false
135-
}
136-
}
137-
ManualThreads(e0a) => {
138-
match (*other) {
139-
ManualThreads(e0b) => e0a == e0b,
140-
_ => false
141-
}
142-
}
143-
PlatformThread => {
144-
match (*other) {
145-
PlatformThread => true,
146-
_ => false
147-
}
148-
}
149-
}
150-
}
151-
pure fn ne(&self, other: &SchedMode) -> bool {
152-
!(*self).eq(other)
153-
}
154127
}
155128

156129
/**
@@ -204,7 +177,7 @@ pub type TaskOpts = {
204177
linked: bool,
205178
supervised: bool,
206179
mut notify_chan: Option<Chan<TaskResult>>,
207-
sched: Option<SchedOpts>,
180+
sched: SchedOpts,
208181
};
209182

210183
/**
@@ -370,7 +343,7 @@ impl TaskBuilder {
370343
linked: self.opts.linked,
371344
supervised: self.opts.supervised,
372345
mut notify_chan: move notify_chan,
373-
sched: Some({ mode: mode, foreign_stack_size: None})
346+
sched: { mode: mode, foreign_stack_size: None}
374347
},
375348
can_not_copy: None,
376349
.. self.consume()
@@ -486,7 +459,10 @@ pub fn default_task_opts() -> TaskOpts {
486459
linked: true,
487460
supervised: false,
488461
mut notify_chan: None,
489-
sched: None
462+
sched: {
463+
mode: DefaultScheduler,
464+
foreign_stack_size: None
465+
}
490466
}
491467
}
492468
@@ -539,10 +515,9 @@ pub fn spawn_with<A:Owned>(arg: A, f: fn~(v: A)) {
539515
540516
pub fn spawn_sched(mode: SchedMode, f: fn~()) {
541517
/*!
542-
* Creates a new scheduler and executes a task on it
543-
*
544-
* Tasks subsequently spawned by that task will also execute on
545-
* the new scheduler. When there are no more tasks to execute the
518+
* Creates a new task on a new or existing scheduler
519+
520+
* When there are no more tasks to execute the
546521
* scheduler terminates.
547522
*
548523
* # Failure
@@ -590,6 +565,10 @@ pub fn get_task() -> Task {
590565
TaskHandle(rt::get_task_id())
591566
}
592567

568+
pub fn get_scheduler() -> Scheduler {
569+
SchedulerHandle(rt::rust_get_sched_id())
570+
}
571+
593572
/**
594573
* Temporarily make the task unkillable
595574
*
@@ -927,16 +906,19 @@ fn test_spawn_sched() {
927906
}
928907

929908
#[test]
930-
fn test_spawn_sched_childs_on_same_sched() {
909+
fn test_spawn_sched_childs_on_default_sched() {
931910
let po = oldcomm::Port();
932911
let ch = oldcomm::Chan(&po);
933912

913+
// Assuming tests run on the default scheduler
914+
let default_id = rt::rust_get_sched_id();
915+
934916
do spawn_sched(SingleThreaded) {
935917
let parent_sched_id = rt::rust_get_sched_id();
936918
do spawn {
937919
let child_sched_id = rt::rust_get_sched_id();
938-
// This should be on the same scheduler
939-
assert parent_sched_id == child_sched_id;
920+
assert parent_sched_id != child_sched_id;
921+
assert child_sched_id == default_id;
940922
oldcomm::send(ch, ());
941923
};
942924
};
@@ -1206,7 +1188,7 @@ fn test_spawn_thread_on_demand() {
12061188

12071189
let (port2, chan2) = pipes::stream();
12081190

1209-
do spawn() |move chan2| {
1191+
do spawn_sched(CurrentScheduler) |move chan2| {
12101192
chan2.send(());
12111193
}
12121194

src/libcore/task/spawn.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ use task::rt::rust_closure;
8888
use task::rt;
8989
use task::{Failure, ManualThreads, PlatformThread, SchedOpts, SingleThreaded};
9090
use task::{Success, TaskOpts, TaskResult, ThreadPerCore, ThreadPerTask};
91+
use task::{ExistingScheduler, SchedulerHandle};
9192
use task::{default_task_opts, unkillable};
9293
use uint;
9394
use util;
@@ -525,9 +526,9 @@ pub fn spawn_raw(opts: TaskOpts, f: fn~()) {
525526
// Agh. Get move-mode items into the closure. FIXME (#2829)
526527
let (child_tg, ancestors, f) = option::swap_unwrap(child_data);
527528
// Create child task.
528-
let new_task = match opts.sched {
529-
None => rt::new_task(),
530-
Some(sched_opts) => new_task_in_new_sched(sched_opts)
529+
let new_task = match opts.sched.mode {
530+
DefaultScheduler => rt::new_task(),
531+
_ => new_task_in_sched(opts.sched)
531532
};
532533
assert !new_task.is_null();
533534
// Getting killed after here would leak the task.
@@ -631,12 +632,16 @@ pub fn spawn_raw(opts: TaskOpts, f: fn~()) {
631632
}
632633
}
633634

634-
fn new_task_in_new_sched(opts: SchedOpts) -> *rust_task {
635+
fn new_task_in_sched(opts: SchedOpts) -> *rust_task {
635636
if opts.foreign_stack_size != None {
636637
fail ~"foreign_stack_size scheduler option unimplemented";
637638
}
638639

639640
let num_threads = match opts.mode {
641+
DefaultScheduler
642+
| CurrentScheduler
643+
| ExistingScheduler(*)
644+
| PlatformThread => 0u, /* Won't be used */
640645
SingleThreaded => 1u,
641646
ThreadPerCore => rt::rust_num_threads(),
642647
ThreadPerTask => {
@@ -648,13 +653,13 @@ pub fn spawn_raw(opts: TaskOpts, f: fn~()) {
648653
}
649654
threads
650655
}
651-
PlatformThread => 0u /* Won't be used */
652656
};
653657

654-
let sched_id = if opts.mode != PlatformThread {
655-
rt::rust_new_sched(num_threads)
656-
} else {
657-
rt::rust_osmain_sched_id()
658+
let sched_id = match opts.mode {
659+
CurrentScheduler => rt::rust_get_sched_id(),
660+
ExistingScheduler(SchedulerHandle(id)) => id,
661+
PlatformThread => rt::rust_osmain_sched_id(),
662+
_ => rt::rust_new_sched(num_threads)
658663
};
659664
rt::rust_new_task_in_sched(sched_id)
660665
}

src/rt/rust.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
4343

4444
rust_kernel *kernel = new rust_kernel(env);
4545

46-
// Create the main scheduler and the main task
47-
rust_sched_id sched_id = kernel->create_scheduler(env->num_sched_threads);
46+
// Create the main task
47+
rust_sched_id sched_id = kernel->main_sched_id();
4848
rust_scheduler *sched = kernel->get_scheduler_by_id(sched_id);
4949
assert(sched != NULL);
5050
rust_task *root_task = sched->create_task(NULL, "main");

src/rt/rust_builtin.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,10 @@ new_task_common(rust_scheduler *sched, rust_task *parent) {
631631
extern "C" CDECL rust_task*
632632
new_task() {
633633
rust_task *task = rust_get_current_task();
634-
return new_task_common(task->sched, task);
634+
rust_sched_id sched_id = task->kernel->main_sched_id();
635+
rust_scheduler *sched = task->kernel->get_scheduler_by_id(sched_id);
636+
assert(sched != NULL && "should always have a main scheduler");
637+
return new_task_common(sched, task);
635638
}
636639

637640
extern "C" CDECL rust_task*

0 commit comments

Comments
 (0)