Ejemplo n.º 1
0
rust_sched_loop_state
rust_sched_loop::run_single_turn() {
    DLOG(this, task,
         "scheduler %d resuming ...", id);

    lock.lock();

    if (!should_exit) {
        assert(dead_task == NULL && "Tasks should only die after running");

        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
             id, number_of_live_tasks());

        rust_task *scheduled_task = schedule_task();

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);

            lock.unlock();
            return sched_loop_state_block;
        }

        scheduled_task->assert_is_running();

        DLOG(this, task,
             "activating task %s 0x%" PRIxPTR
             ", state: %s",
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             state_name(scheduled_task->get_state()));

        place_task_in_tls(scheduled_task);

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        activate(scheduled_task);

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             state_name(scheduled_task->get_state()),
             id);

        reap_dead_tasks();

        lock.unlock();
        return sched_loop_state_keep_going;
    } else {
        assert(running_tasks.is_empty() && "Should have no running tasks");
        assert(blocked_tasks.is_empty() && "Should have no blocked tasks");
        assert(dead_task == NULL && "Should have no dead tasks");

        DLOG(this, dom, "finished main-loop %d", id);

        lock.unlock();

        assert(!extra_c_stack);
        if (cached_c_stack) {
            destroy_exchange_stack(kernel->region(), cached_c_stack);
            cached_c_stack = NULL;
        }
        assert(!extra_big_stack);
        if (cached_big_stack) {
            destroy_exchange_stack(kernel->region(), cached_big_stack);
            cached_big_stack = NULL;
        }

        sched->release_task_thread();
        return sched_loop_state_exit;
    }
}
Ejemplo n.º 2
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
int
rust_scheduler::start_main_loop(int id) {
    kernel->scheduler_lock.lock();

    // Make sure someone is watching, to pull us out of infinite loops.
    //
    // FIXME: time-based interruption is not presently working; worked
    // in rustboot and has been completely broken in rustc.
    //
    // rust_timer timer(this);

    DLOG(this, dom, "started domain loop %d", id);

    while (number_of_live_tasks() > 0) {
        A(this, kernel->is_deadlocked() == false, "deadlock");

        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
             id, number_of_live_tasks());

        drain_incoming_message_queue(true);

        rust_task *scheduled_task = schedule_task(id);

        // The scheduler busy waits until a task is available for scheduling.
        // Eventually we'll want a smarter way to do this, perhaps sleep
        // for a minimum amount of time.

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);
            kernel->scheduler_lock.unlock();
            sync::sleep(100);
            kernel->scheduler_lock.lock();
            DLOG(this, task,
                "scheduler resuming ...");
            continue;
        }

        I(this, scheduled_task->running());

        DLOG(this, task,
            "activating task %s 0x%" PRIxPTR
            ", sp=0x%" PRIxPTR
            ", ref_count=%d"
            ", state: %s",
            scheduled_task->name,
            (uintptr_t)scheduled_task,
            scheduled_task->rust_sp,
            scheduled_task->ref_count,
            scheduled_task->state->name);

        interrupt_flag = 0;

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        scheduled_task->running_on = id;
        activate(scheduled_task);
        scheduled_task->running_on = -1;

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->state->name,
             scheduled_task->rust_sp,
             id);

        reap_dead_tasks(id);
    }

    DLOG(this, dom,
         "terminated scheduler loop, reaping dead tasks ...");

    while (dead_tasks.length() > 0) {
        if (message_queue->is_empty()) {
            DLOG(this, dom,
                "waiting for %d dead tasks to become dereferenced, "
                "scheduler yielding ...",
                dead_tasks.length());
            log_state();
            kernel->scheduler_lock.unlock();
            sync::yield();
            kernel->scheduler_lock.lock();
        } else {
            drain_incoming_message_queue(true);
        }
        reap_dead_tasks(id);
    }

    DLOG(this, dom, "finished main-loop %d (dom.rval = %d)", id, rval);

    kernel->scheduler_lock.unlock();
    return rval;
}
Ejemplo n.º 3
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
void
rust_scheduler::start_main_loop() {
    lock.lock();

    // Make sure someone is watching, to pull us out of infinite loops.
    //
    // FIXME: time-based interruption is not presently working; worked
    // in rustboot and has been completely broken in rustc.
    //
    // rust_timer timer(this);

    DLOG(this, dom, "started domain loop %d", id);

    while (kernel->live_tasks > 0) {
        A(this, kernel->is_deadlocked() == false, "deadlock");

        DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d",
             id, number_of_live_tasks(), kernel->live_tasks);

        rust_task *scheduled_task = schedule_task(id);

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);
            lock.timed_wait(10);
            reap_dead_tasks(id);
            DLOG(this, task,
                 "scheduler %d resuming ...", id);
            continue;
        }

        I(this, scheduled_task->running());

        DLOG(this, task,
             "activating task %s 0x%" PRIxPTR
             ", sp=0x%" PRIxPTR
             ", state: %s",
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->user.rust_sp,
             scheduled_task->state->name);

        place_task_in_tls(scheduled_task);

        interrupt_flag = 0;

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        scheduled_task->running_on = id;
        activate(scheduled_task);
        scheduled_task->running_on = -1;

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->state->name,
             scheduled_task->user.rust_sp,
             id);

        reap_dead_tasks(id);
    }

    DLOG(this, dom,
         "terminated scheduler loop, reaping dead tasks ...");

    while (dead_tasks.length() > 0) {
        DLOG(this, dom,
             "waiting for %d dead tasks to become dereferenced, "
             "scheduler yielding ...",
             dead_tasks.length());
        log_state();
        lock.unlock();
        sync::yield();
        lock.lock();
        reap_dead_tasks(id);
    }

    DLOG(this, dom, "finished main-loop %d", id);

    lock.unlock();
}
Ejemplo n.º 4
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
int
rust_dom::start_main_loop()
{
    // Make sure someone is watching, to pull us out of infinite loops.
    rust_timer timer(this);

    log(rust_log::DOM, "running main-loop on domain %s @0x%" PRIxPTR,
        name, this);
    logptr("exit-task glue", root_crate->get_exit_task_glue());

    while (n_live_tasks() > 0) {
        A(this, is_deadlocked() == false, "deadlock");

        drain_incoming_message_queue(true);

        rust_task *scheduled_task = schedule_task();

        // The scheduler busy waits until a task is available for scheduling.
        // Eventually we'll want a smarter way to do this, perhaps sleep
        // for a minimum amount of time.

        if (scheduled_task == NULL) {
            if (_log.is_tracing(rust_log::TASK)) {
                log_state();
            }
            log(rust_log::TASK,
                "all tasks are blocked, scheduler yielding ...");
            sync::yield();
            log(rust_log::TASK,
                "scheduler resuming ...");
            continue;
        }

        I(this, scheduled_task->running());

        log(rust_log::TASK,
            "activating task %s 0x%" PRIxPTR
            ", sp=0x%" PRIxPTR
            ", ref_count=%d"
            ", state: %s",
            scheduled_task->name,
            (uintptr_t)scheduled_task,
            scheduled_task->rust_sp,
            scheduled_task->ref_count,
            scheduled_task->state_str());

        interrupt_flag = 0;

        activate(scheduled_task);

        log(rust_log::TASK,
                 "returned from task %s @0x%" PRIxPTR
                 " in state '%s', sp=0x%" PRIxPTR,
                 scheduled_task->name,
                 (uintptr_t)scheduled_task,
                 state_vec_name(scheduled_task->state),
                 scheduled_task->rust_sp);

        I(this, scheduled_task->rust_sp >=
          (uintptr_t) &scheduled_task->stk->data[0]);
        I(this, scheduled_task->rust_sp < scheduled_task->stk->limit);

        reap_dead_tasks();
    }

    log(rust_log::DOM, "terminated scheduler loop, reaping dead tasks ...");

    while (dead_tasks.length() > 0) {
        if (_incoming_message_queue.is_empty()) {
            log(rust_log::DOM,
                "waiting for %d dead tasks to become dereferenced, "
                "scheduler yielding ...",
                dead_tasks.length());
            if (_log.is_tracing(rust_log::TASK)) {
                log_state();
            }
            sync::yield();
        } else {
            drain_incoming_message_queue(true);
        }
        reap_dead_tasks();
    }

    log(rust_log::DOM, "finished main-loop (dom.rval = %d)", rval);
    return rval;
}
Ejemplo n.º 5
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
void
rust_task_thread::start_main_loop() {
    lock.lock();

    DLOG(this, dom, "started domain loop %d", id);

    while (!should_exit) {
        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
             id, number_of_live_tasks());

        rust_task *scheduled_task = schedule_task();

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);
            lock.wait();
            reap_dead_tasks();
            DLOG(this, task,
                 "scheduler %d resuming ...", id);
            continue;
        }

        I(this, scheduled_task->running());

        DLOG(this, task,
             "activating task %s 0x%" PRIxPTR
             ", sp=0x%" PRIxPTR
             ", state: %s",
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->user.rust_sp,
             scheduled_task->state->name);

        place_task_in_tls(scheduled_task);

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        activate(scheduled_task);

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->state->name,
             scheduled_task->user.rust_sp,
             id);

        reap_dead_tasks();
    }

    A(this, newborn_tasks.is_empty(), "Should have no newborn tasks");
    A(this, running_tasks.is_empty(), "Should have no running tasks");
    A(this, blocked_tasks.is_empty(), "Should have no blocked tasks");
    A(this, dead_tasks.is_empty(), "Should have no dead tasks");

    DLOG(this, dom, "finished main-loop %d", id);

    lock.unlock();
}