Do a task-killed check at the start of task 'timeslices'.

This commit is contained in:
Ben Blum 2013-07-08 19:31:32 -04:00
parent 629f6e8d68
commit e80efe3fda
2 changed files with 38 additions and 1 deletions

View file

@ -15,7 +15,7 @@ use cell::Cell;
use option::{Option, Some, None};
use prelude::*;
use rt::task::Task;
use unstable::atomics::{AtomicUint, SeqCst};
use unstable::atomics::{AtomicUint, Acquire, SeqCst};
use unstable::sync::{UnsafeAtomicRcBox, LittleLock};
use util;
@ -137,6 +137,16 @@ impl KillHandle {
}
}
#[inline]
pub fn killed(&self) -> bool {
// Called every context switch, so shouldn't report true if the task
// is unkillable with a kill signal pending.
let inner = unsafe { &*self.get() };
let flag = unsafe { &*inner.killed.get() };
// FIXME(#6598): can use relaxed ordering (i think)
flag.load(Acquire) == KILL_KILLED
}
pub fn notify_immediate_failure(&mut self) {
// A benign data race may happen here if there are failing sibling
// tasks that were also spawned-watched. The refcount's write barriers
@ -287,6 +297,22 @@ impl Death {
self.unkillable = 0;
}
/// Fails if a kill signal was received.
#[inline]
pub fn check_killed(&self) {
match self.kill_handle {
Some(ref kill_handle) =>
// The task may be both unkillable and killed if it does some
// synchronization during unwinding or cleanup (for example,
// sending on a notify port). In that case failing won't help.
if self.unkillable == 0 && kill_handle.killed() {
fail!(KILLED_MSG);
},
// This may happen during task death (see comments in collect_failure).
None => rtassert!(self.unkillable > 0),
}
}
/// Enter a possibly-nested unkillable section of code.
/// All calls must be paired with a subsequent call to allow_kill.
#[inline]

View file

@ -483,6 +483,11 @@ impl Scheduler {
// Running tasks may have asked us to do some cleanup
(*sched).run_cleanup_job();
// Must happen after running the cleanup job (of course).
// Might not be running in task context; if not, a later call to
// resume_task_immediately will take care of this.
(*sched).current_task.map(|t| t.death.check_killed());
}
}
@ -524,6 +529,9 @@ impl Scheduler {
// We could be executing in a different thread now
let sched = Local::unsafe_borrow::<Scheduler>();
(*sched).run_cleanup_job();
// As above, must happen after running the cleanup job.
(*sched).current_task.map(|t| t.death.check_killed());
}
}
@ -559,6 +567,9 @@ impl Scheduler {
// We could be executing in a different thread now
let sched = Local::unsafe_borrow::<Scheduler>();
(*sched).run_cleanup_job();
// As above, must happen after running the cleanup job.
(*sched).current_task.map(|t| t.death.check_killed());
}
}