Reintroduce linked failure (lifecycle lock)
This reverts commit 08c40c5eb7.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user