From 79a2e9a38a243d30130e32fa0741d7430fc63758 Mon Sep 17 00:00:00 2001 From: Ben Blum Date: Thu, 12 Jul 2012 19:52:13 -0400 Subject: [PATCH] Reintroduce linked failure (lifecycle lock) This reverts commit 08c40c5eb7bda79850f725308b72c1451fb67a86. --- src/rt/rust_sched_loop.cpp | 2 +- src/rt/rust_task.cpp | 67 +++++++++++++++++--------------------- src/rt/rust_task.h | 16 ++++----- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index 4b94968d7c0..ccfdcb5a8ab 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -208,7 +208,7 @@ rust_sched_loop::run_single_turn() { return sched_loop_state_block; } - assert(scheduled_task->running()); + scheduled_task->assert_is_running(); DLOG(this, task, "activating task %s 0x%" PRIxPTR diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index d23d74b0ea2..250e075d2f9 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -114,7 +114,7 @@ cleanup_task(cleanup_args *args) { rust_task *task = a->task; { - scoped_lock with(task->kill_lock); + scoped_lock with(task->lifecycle_lock); if (task->killed && !threw_exception) { LOG(task, task, "Task killed during termination"); threw_exception = true; @@ -230,21 +230,25 @@ void rust_task::start() bool rust_task::must_fail_from_being_killed() { - scoped_lock with(kill_lock); + scoped_lock with(lifecycle_lock); return must_fail_from_being_killed_unlocked(); } bool 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; } // Only run this on the rust stack void rust_task::yield(bool *killed) { + // FIXME (#2787): clean this up if (must_fail_from_being_killed()) { - assert(!blocked()); + { + scoped_lock with(lifecycle_lock); + assert(!(state == task_state_blocked)); + } *killed = true; } @@ -258,7 +262,7 @@ rust_task::yield(bool *killed) { void rust_task::kill() { - scoped_lock with(kill_lock); + scoped_lock with(lifecycle_lock); // XXX: bblum: kill/kill race @@ -270,8 +274,9 @@ rust_task::kill() { killed = true; // Unblock the task so it can unwind. - if (blocked() && must_fail_from_being_killed_unlocked()) { - wakeup(cond); + if (state == task_state_blocked && + must_fail_from_being_killed_unlocked()) { + wakeup_locked(cond); } 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); } -bool -rust_task::running() +void rust_task::assert_is_running() { - scoped_lock with(state_lock); - return state == task_state_running; -} - -bool -rust_task::blocked() -{ - scoped_lock with(state_lock); - return state == task_state_blocked; + scoped_lock with(lifecycle_lock); + assert(state == task_state_running); } +// FIXME (#2851, #2787): This is only used by rust_port/rust_port selector, +// and is inherently racy. Get rid of it. bool rust_task::blocked_on(rust_cond *on) { - scoped_lock with(state_lock); + scoped_lock with(lifecycle_lock); return cond == on; } -bool -rust_task::dead() -{ - scoped_lock with(state_lock); - return state == task_state_dead; -} - void * rust_task::malloc(size_t sz, const char *tag, type_desc *td) { @@ -384,20 +376,20 @@ rust_task::free(void *p) void rust_task::transition(rust_task_state src, rust_task_state dst, rust_cond *cond, const char* cond_name) { - scoped_lock with(state_lock); + scoped_lock with(lifecycle_lock); transition_locked(src, dst, cond, cond_name); } void rust_task::transition_locked(rust_task_state src, rust_task_state dst, 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); } void rust_task::set_state(rust_task_state state, rust_cond *cond, const char* cond_name) { - state_lock.must_have_lock(); + lifecycle_lock.must_have_lock(); this->state = state; this->cond = cond; this->cond_name = cond_name; @@ -405,7 +397,7 @@ rust_task::set_state(rust_task_state state, bool rust_task::block(rust_cond *on, const char* name) { - scoped_lock with(kill_lock); + scoped_lock with(lifecycle_lock); return block_locked(on, name); } @@ -428,7 +420,7 @@ rust_task::block_locked(rust_cond *on, const char* name) { void rust_task::wakeup(rust_cond *from) { - scoped_lock with(state_lock); + scoped_lock with(lifecycle_lock); wakeup_locked(from); } @@ -676,26 +668,27 @@ rust_task::on_rust_stack() { void 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++; } void rust_task::allow_kill() { - scoped_lock with(kill_lock); + scoped_lock with(lifecycle_lock); assert(disallow_kill > 0 && "Illegal allow_kill(): already killable!"); disallow_kill--; } void * rust_task::wait_event(bool *killed) { - scoped_lock with(state_lock); + scoped_lock with(lifecycle_lock); if(!event_reject) { block_locked(&event_cond, "waiting on event"); - state_lock.unlock(); + lifecycle_lock.unlock(); yield(killed); - state_lock.lock(); + lifecycle_lock.lock(); } event_reject = false; @@ -704,7 +697,7 @@ rust_task::wait_event(bool *killed) { void rust_task::signal_event(void *event) { - scoped_lock with(state_lock); + scoped_lock with(lifecycle_lock); this->event = event; event_reject = true; diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 3bde5202954..82896bf27b4 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -170,7 +170,8 @@ rust_task : public kernel_owned private: // 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_cond *cond; const char *cond_name; @@ -179,8 +180,6 @@ private: rust_cond event_cond; 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 bool killed; // Indicates that we've called back into Rust from C @@ -243,10 +242,8 @@ public: rust_opaque_box *env, void *args); void start(); - bool running(); - bool blocked(); - bool blocked_on(rust_cond *cond); - bool dead(); + void assert_is_running(); + bool blocked_on(rust_cond *cond); // FIXME (#2851) Get rid of this. void *malloc(size_t sz, const char *tag, type_desc *td=0); 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; { - scoped_lock with(kill_lock); + // FIXME (#2787) This must be racy. Figure it out. + scoped_lock with(lifecycle_lock); 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; { - scoped_lock with(kill_lock); + scoped_lock with(lifecycle_lock); reentered_rust_stack = had_reentered_rust_stack; }