Reintroduce linked failure (lifecycle lock)

This reverts commit 08c40c5eb7.
This commit is contained in:
Ben Blum
2012-07-12 19:52:13 -04:00
parent df2d2604ca
commit 79a2e9a38a
3 changed files with 38 additions and 47 deletions

View File

@@ -208,7 +208,7 @@ rust_sched_loop::run_single_turn() {
return sched_loop_state_block; return sched_loop_state_block;
} }
assert(scheduled_task->running()); scheduled_task->assert_is_running();
DLOG(this, task, DLOG(this, task,
"activating task %s 0x%" PRIxPTR "activating task %s 0x%" PRIxPTR

View File

@@ -114,7 +114,7 @@ cleanup_task(cleanup_args *args) {
rust_task *task = a->task; rust_task *task = a->task;
{ {
scoped_lock with(task->kill_lock); scoped_lock with(task->lifecycle_lock);
if (task->killed && !threw_exception) { if (task->killed && !threw_exception) {
LOG(task, task, "Task killed during termination"); LOG(task, task, "Task killed during termination");
threw_exception = true; threw_exception = true;
@@ -230,21 +230,25 @@ void rust_task::start()
bool bool
rust_task::must_fail_from_being_killed() { rust_task::must_fail_from_being_killed() {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
return must_fail_from_being_killed_unlocked(); return must_fail_from_being_killed_unlocked();
} }
bool bool
rust_task::must_fail_from_being_killed_unlocked() { rust_task::must_fail_from_being_killed_unlocked() {
kill_lock.must_have_lock(); lifecycle_lock.must_have_lock();
return killed && !reentered_rust_stack && disallow_kill == 0; return killed && !reentered_rust_stack && disallow_kill == 0;
} }
// Only run this on the rust stack // Only run this on the rust stack
void void
rust_task::yield(bool *killed) { rust_task::yield(bool *killed) {
// FIXME (#2787): clean this up
if (must_fail_from_being_killed()) { if (must_fail_from_being_killed()) {
assert(!blocked()); {
scoped_lock with(lifecycle_lock);
assert(!(state == task_state_blocked));
}
*killed = true; *killed = true;
} }
@@ -258,7 +262,7 @@ rust_task::yield(bool *killed) {
void void
rust_task::kill() { rust_task::kill() {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
// XXX: bblum: kill/kill race // XXX: bblum: kill/kill race
@@ -270,8 +274,9 @@ rust_task::kill() {
killed = true; killed = true;
// Unblock the task so it can unwind. // Unblock the task so it can unwind.
if (blocked() && must_fail_from_being_killed_unlocked()) { if (state == task_state_blocked &&
wakeup(cond); must_fail_from_being_killed_unlocked()) {
wakeup_locked(cond);
} }
LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this); LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this);
@@ -335,34 +340,21 @@ rust_task::get_frame_glue_fns(uintptr_t fp) {
return *((frame_glue_fns**) fp); return *((frame_glue_fns**) fp);
} }
bool void rust_task::assert_is_running()
rust_task::running()
{ {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
return state == task_state_running; assert(state == task_state_running);
}
bool
rust_task::blocked()
{
scoped_lock with(state_lock);
return state == task_state_blocked;
} }
// FIXME (#2851, #2787): This is only used by rust_port/rust_port selector,
// and is inherently racy. Get rid of it.
bool bool
rust_task::blocked_on(rust_cond *on) rust_task::blocked_on(rust_cond *on)
{ {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
return cond == on; return cond == on;
} }
bool
rust_task::dead()
{
scoped_lock with(state_lock);
return state == task_state_dead;
}
void * void *
rust_task::malloc(size_t sz, const char *tag, type_desc *td) rust_task::malloc(size_t sz, const char *tag, type_desc *td)
{ {
@@ -384,20 +376,20 @@ rust_task::free(void *p)
void void
rust_task::transition(rust_task_state src, rust_task_state dst, rust_task::transition(rust_task_state src, rust_task_state dst,
rust_cond *cond, const char* cond_name) { rust_cond *cond, const char* cond_name) {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
transition_locked(src, dst, cond, cond_name); transition_locked(src, dst, cond, cond_name);
} }
void rust_task::transition_locked(rust_task_state src, rust_task_state dst, void rust_task::transition_locked(rust_task_state src, rust_task_state dst,
rust_cond *cond, const char* cond_name) { rust_cond *cond, const char* cond_name) {
state_lock.must_have_lock(); lifecycle_lock.must_have_lock();
sched_loop->transition(this, src, dst, cond, cond_name); sched_loop->transition(this, src, dst, cond, cond_name);
} }
void void
rust_task::set_state(rust_task_state state, rust_task::set_state(rust_task_state state,
rust_cond *cond, const char* cond_name) { rust_cond *cond, const char* cond_name) {
state_lock.must_have_lock(); lifecycle_lock.must_have_lock();
this->state = state; this->state = state;
this->cond = cond; this->cond = cond;
this->cond_name = cond_name; this->cond_name = cond_name;
@@ -405,7 +397,7 @@ rust_task::set_state(rust_task_state state,
bool bool
rust_task::block(rust_cond *on, const char* name) { rust_task::block(rust_cond *on, const char* name) {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
return block_locked(on, name); return block_locked(on, name);
} }
@@ -428,7 +420,7 @@ rust_task::block_locked(rust_cond *on, const char* name) {
void void
rust_task::wakeup(rust_cond *from) { rust_task::wakeup(rust_cond *from) {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
wakeup_locked(from); wakeup_locked(from);
} }
@@ -676,26 +668,27 @@ rust_task::on_rust_stack() {
void void
rust_task::inhibit_kill() { rust_task::inhibit_kill() {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
// FIXME (#1868) Check here if we have to die
disallow_kill++; disallow_kill++;
} }
void void
rust_task::allow_kill() { rust_task::allow_kill() {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
assert(disallow_kill > 0 && "Illegal allow_kill(): already killable!"); assert(disallow_kill > 0 && "Illegal allow_kill(): already killable!");
disallow_kill--; disallow_kill--;
} }
void * void *
rust_task::wait_event(bool *killed) { rust_task::wait_event(bool *killed) {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
if(!event_reject) { if(!event_reject) {
block_locked(&event_cond, "waiting on event"); block_locked(&event_cond, "waiting on event");
state_lock.unlock(); lifecycle_lock.unlock();
yield(killed); yield(killed);
state_lock.lock(); lifecycle_lock.lock();
} }
event_reject = false; event_reject = false;
@@ -704,7 +697,7 @@ rust_task::wait_event(bool *killed) {
void void
rust_task::signal_event(void *event) { rust_task::signal_event(void *event) {
scoped_lock with(state_lock); scoped_lock with(lifecycle_lock);
this->event = event; this->event = event;
event_reject = true; event_reject = true;

View File

@@ -170,7 +170,8 @@ rust_task : public kernel_owned<rust_task>
private: private:
// Protects state, cond, cond_name // Protects state, cond, cond_name
lock_and_signal state_lock; // Protects the killed flag, disallow_kill flag, reentered_rust_stack
lock_and_signal lifecycle_lock;
rust_task_state state; rust_task_state state;
rust_cond *cond; rust_cond *cond;
const char *cond_name; const char *cond_name;
@@ -179,8 +180,6 @@ private:
rust_cond event_cond; rust_cond event_cond;
void *event; void *event;
// Protects the killed flag, disallow_kill flag, reentered_rust_stack
lock_and_signal kill_lock;
// Indicates that the task was killed and needs to unwind // Indicates that the task was killed and needs to unwind
bool killed; bool killed;
// Indicates that we've called back into Rust from C // Indicates that we've called back into Rust from C
@@ -243,10 +242,8 @@ public:
rust_opaque_box *env, rust_opaque_box *env,
void *args); void *args);
void start(); void start();
bool running(); void assert_is_running();
bool blocked(); bool blocked_on(rust_cond *cond); // FIXME (#2851) Get rid of this.
bool blocked_on(rust_cond *cond);
bool dead();
void *malloc(size_t sz, const char *tag, type_desc *td=0); void *malloc(size_t sz, const char *tag, type_desc *td=0);
void *realloc(void *data, size_t sz); void *realloc(void *data, size_t sz);
@@ -438,7 +435,8 @@ rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
bool had_reentered_rust_stack = reentered_rust_stack; bool had_reentered_rust_stack = reentered_rust_stack;
{ {
scoped_lock with(kill_lock); // FIXME (#2787) This must be racy. Figure it out.
scoped_lock with(lifecycle_lock);
reentered_rust_stack = true; reentered_rust_stack = true;
} }
@@ -453,7 +451,7 @@ rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
next_c_sp = prev_c_sp; next_c_sp = prev_c_sp;
{ {
scoped_lock with(kill_lock); scoped_lock with(lifecycle_lock);
reentered_rust_stack = had_reentered_rust_stack; reentered_rust_stack = had_reentered_rust_stack;
} }