Skip to content

Commit

Permalink
added functionality to tell schedulers to refuse to run tasks that ar…
Browse files Browse the repository at this point in the history
…e not pinned to them
  • Loading branch information
toddaaro committed Jun 12, 2013
1 parent 8428081 commit 4224fc7
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 18 deletions.
48 changes: 35 additions & 13 deletions src/libstd/rt/sched.rs
Expand Up @@ -70,7 +70,9 @@ pub struct Scheduler {
/// An action performed after a context switch on behalf of the
/// code running before the context switch
priv cleanup_job: Option<CleanupJob>,
metrics: SchedMetrics
metrics: SchedMetrics,
/// Should this scheduler run any task, or only pinned tasks?
run_anything: bool
}

pub struct SchedHandle {
Expand Down Expand Up @@ -136,6 +138,16 @@ pub impl Scheduler {
sleeper_list: SleeperList)
-> Scheduler {

Scheduler::new_special(event_loop, work_queue, sleeper_list, true)

}

fn new_special(event_loop: ~EventLoopObject,
work_queue: WorkQueue<~Coroutine>,
sleeper_list: SleeperList,
run_anything: bool)
-> Scheduler {

// Lazily initialize the runtime TLS key
local_ptr::init_tls_key();

Expand All @@ -150,7 +162,8 @@ pub impl Scheduler {
saved_context: Context::empty(),
current_task: None,
cleanup_job: None,
metrics: SchedMetrics::new()
metrics: SchedMetrics::new(),
run_anything: run_anything
}
}

Expand Down Expand Up @@ -429,19 +442,28 @@ pub impl Scheduler {
assert!(!self.in_task_context());

rtdebug!("looking in work queue for task to schedule");

let mut this = self;
match this.work_queue.pop() {
Some(task) => {
rtdebug!("resuming task from work queue");
this.resume_task_immediately(task);
return true;
}
None => {
rtdebug!("no tasks in queue");
Local::put(this);
return false;

if this.run_anything {
match this.work_queue.pop() {
Some(task) => {
rtdebug!("resuming task from work queue");
this.resume_task_immediately(task);
return true;
}
None => {
rtdebug!("no tasks in queue");
Local::put(this);
return false;
}
}
} else {
// In this branch we have a scheduler that is not allowed
// to run unpinned tasks. As such it will only get tasks
// to run from the message queue.
rtdebug!("skipping resume_task_from_queue");
Local::put(this);
return false;
}
}

Expand Down
30 changes: 25 additions & 5 deletions src/libstd/rt/test.rs
Expand Up @@ -157,23 +157,43 @@ pub fn run_in_mt_newsched_task_random_homed() {
let mut handles = ~[];
let mut scheds = ~[];

for uint::range(0, nthreads) |_| {
// create a few special schedulers, those with even indicies
// will be pinned-only
for uint::range(0, nthreads) |i| {
let special = (i % 2) == 0;
let loop_ = ~UvEventLoop::new();
let mut sched = ~Scheduler::new(loop_, work_queue.clone(), sleepers.clone());
let mut sched = ~Scheduler::new_special(loop_, work_queue.clone(), sleepers.clone(), special);
let handle = sched.make_handle();
handles.push(handle);
scheds.push(sched);
}
}

// Schedule a pile o tasks
let n = 120*stress_factor();
let n = 5*stress_factor();
for uint::range(0,n) |_i| {
rtdebug!("creating task: %u", _i);
let hf: ~fn() = || { assert!(true) };
spawntask_homed(&mut scheds, hf);
}

let f: ~fn() = || { assert!(true); };
// Now we want another pile o tasks that do not ever run on a
// special scheduler, because they are normal tasks. Because
// we can we put these in the "main" task.

let n = 5*stress_factor();

let f: ~fn() = || {
for uint::range(0,n) |_| {
let f: ~fn() = || {
// Borrow the scheduler we run on and check if it is
// privliged.
do Local::borrow::<Scheduler,()> |sched| {
assert!(sched.run_anything);
};
};
spawntask_random(f);
};
};

let f_cell = Cell(f);
let handles = Cell(handles);
Expand Down

0 comments on commit 4224fc7

Please sign in to comment.