Esempio n. 1
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();
}
Esempio n. 2
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;
    }
}
Esempio 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_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();
}