bool rust_task::block_locked(rust_cond *on, const char* name) { if (must_fail_from_being_killed_unlocked()) { // We're already going to die. Don't block. Tell the task to fail return false; } LOG(this, task, "Blocking on 0x%" PRIxPTR ", cond: 0x%" PRIxPTR, (uintptr_t) on, (uintptr_t) cond); assert(cond == NULL && "Cannot block an already blocked task."); assert(on != NULL && "Cannot block on a NULL object."); transition_locked(task_state_running, task_state_blocked, on, name); return true; }
void rust_task::kill() { scoped_lock with(kill_lock); if (dead()) { // Task is already dead, can't kill what's already dead. fail_parent(); } // Note the distinction here: kill() is when you're in an upcall // from task A and want to force-fail task B, you do B->kill(). // If you want to fail yourself you do self->fail(). LOG(this, task, "killing task %s @0x%" PRIxPTR, name, this); // When the task next goes to yield or resume it will fail killed = true; // Unblock the task so it can unwind. if (blocked() && must_fail_from_being_killed_unlocked()) { wakeup(cond); } LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this); }
bool rust_task::must_fail_from_being_killed() { scoped_lock with(kill_lock); return must_fail_from_being_killed_unlocked(); }