Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fire fewer homing missiles #10070

Merged
merged 1 commit into from
Oct 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/libstd/rt/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,12 @@ impl Scheduler {
this.process_task(task, Scheduler::resume_task_immediately_cl);
return None;
}
Some(RunOnce(task)) => {
// bypass the process_task logic to force running this task once
// on this home scheduler. This is often used for I/O (homing).
Scheduler::resume_task_immediately_cl(this, task);
return None;
}
Some(Wake) => {
this.sleepy = false;
Local::put(this);
Expand Down Expand Up @@ -789,7 +795,8 @@ pub enum SchedMessage {
Wake,
Shutdown,
PinnedTask(~Task),
TaskFromFriend(~Task)
TaskFromFriend(~Task),
RunOnce(~Task),
}

pub struct SchedHandle {
Expand Down
76 changes: 41 additions & 35 deletions src/libstd/rt/uv/uvio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use rt::local::Local;
use rt::rtio::*;
use rt::sched::{Scheduler, SchedHandle};
use rt::tube::Tube;
use rt::task::SchedHome;
use rt::task::Task;
use rt::uv::*;
use rt::uv::idle::IdleWatcher;
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
Expand Down Expand Up @@ -59,66 +59,72 @@ trait HomingIO {

fn home<'r>(&'r mut self) -> &'r mut SchedHandle;

/* XXX This will move pinned tasks to do IO on the proper scheduler
* and then move them back to their home.
*/
fn go_to_IO_home(&mut self) -> SchedHome {
use rt::sched::PinnedTask;
/// This function will move tasks to run on their home I/O scheduler. Note
/// that this function does *not* pin the task to the I/O scheduler, but
/// rather it simply moves it to running on the I/O scheduler.
fn go_to_IO_home(&mut self) -> uint {
use rt::sched::RunOnce;

do task::unkillable { // FIXME(#8674)
let mut old = None;
{
let ptr = &mut old;
let current_sched_id = do Local::borrow |sched: &mut Scheduler| {
sched.sched_id()
};

// Only need to invoke a context switch if we're not on the right
// scheduler.
if current_sched_id != self.home().sched_id {
do task::unkillable { // FIXME(#8674)
let scheduler: ~Scheduler = Local::take();
do scheduler.deschedule_running_task_and_then |_, task| {
/* FIXME(#8674) if the task was already killed then wake
* will return None. In that case, the home pointer will never be set.
* will return None. In that case, the home pointer will
* never be set.
*
* RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
* RESOLUTION IDEA: Since the task is dead, we should
* just abort the IO action.
*/
do task.wake().map |mut task| {
*ptr = Some(task.take_unwrap_home());
self.home().send(PinnedTask(task));
do task.wake().map |task| {
self.home().send(RunOnce(task));
};
}
}
old.expect("No old home because task had already been killed.")
}

self.home().sched_id
}

// XXX dummy self param
fn restore_original_home(_dummy_self: Option<Self>, old: SchedHome) {
use rt::sched::TaskFromFriend;
// XXX: dummy self parameter
fn restore_original_home(_: Option<Self>, io_home: uint) {
// It would truly be a sad day if we had moved off the home I/O
// scheduler while we were doing I/O.
assert_eq!(Local::borrow(|sched: &mut Scheduler| sched.sched_id()),
io_home);

let old = Cell::new(old);
do task::unkillable { // FIXME(#8674)
let scheduler: ~Scheduler = Local::take();
do scheduler.deschedule_running_task_and_then |scheduler, task| {
/* FIXME(#8674) if the task was already killed then wake
* will return None. In that case, the home pointer will never be restored.
*
* RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
*/
do task.wake().map |mut task| {
task.give_home(old.take());
scheduler.make_handle().send(TaskFromFriend(task));
};
// If we were a homed task, then we must send ourselves back to the
// original scheduler. Otherwise, we can just return and keep running
if !Task::on_appropriate_sched() {
do task::unkillable { // FIXME(#8674)
let scheduler: ~Scheduler = Local::take();
do scheduler.deschedule_running_task_and_then |_, task| {
do task.wake().map |task| {
Scheduler::run_task(task);
};
}
}
}
}

fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
let home = self.go_to_IO_home();
let a = io(self); // do IO
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
HomingIO::restore_original_home(None::<Self>, home);
a // return the result of the IO
}

fn home_for_io_consume<A>(self, io: &fn(Self) -> A) -> A {
let mut this = self;
let home = this.go_to_IO_home();
let a = io(this); // do IO
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
HomingIO::restore_original_home(None::<Self>, home);
a // return the result of the IO
}

Expand All @@ -128,7 +134,7 @@ trait HomingIO {
let scheduler: ~Scheduler = Local::take();
io_sched(self, scheduler) // do IO and scheduling action
};
HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
HomingIO::restore_original_home(None::<Self>, home);
a // return result of IO
}
}
Expand Down