Ejemplo n.º 1
0
errval_t wait_for_all_spawnds(void)
{
    // Note: The whole wait for all_spawnds_up thing is a hack.
    // Our overall design goal is a system where cores
    // come and go dynamically and we do not want / need
    // to wait for a stable state.
    // However, some of our code (for example domain spanning)
    // still assumes a fixed set of cores and will deadlock
    // otherwise. Therefore we need to fix those parts first.
    KALUGA_DEBUG("Waiting for acpi");
    char* record = NULL;
    errval_t err = oct_wait_for(&record, "acpi { iref: _ }");
    free(record);
    if (err_is_fail(err)) {
        return err_push(err, KALUGA_ERR_WAITING_FOR_ACPI);
    }

    // No we should be able to get core count
    // of all cores to estimate the amount of
    // spawnd's we have to expect (one per core)
    char** names;
    size_t count;
    err = oct_get_names(&names, &count, local_apics);
    if (err_is_fail(err)) {
        return err_push(err, KALUGA_ERR_QUERY_LOCAL_APIC);
    }
    oct_free_names(names, count);

    static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
    octopus_trigger_id_t tid;
    return oct_trigger_existing_and_watch(spawnds, spawnd_change_event, (void*)count, &tid);
}
Ejemplo n.º 2
0
/**
 * \brief Client enters a barrier. Blocks until all clients have entered the
 * barrier.
 *
 * Each client creates a (sequential record) based on the provided name.
 * Once a client sees the specified amount (wait_for) of records it
 * creates a record that wakes up all waiting clients.
 *
 * \param[in] name Name of the barrier.
 * \param[out] barrier_record Record created for each client.
 * \param[in] wait_for Number of clients entering the barrier.
 */
errval_t oct_barrier_enter(const char* name, char** barrier_record, size_t wait_for)
{
    errval_t err;
    errval_t exist_err;
    char* record = NULL;
    char** names = NULL;
    uint64_t mode = 0;
    uint64_t state = 0;
    uint64_t fn = 0;
    octopus_trigger_id_t tid;
    size_t current_barriers = 0;
    octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD, octopus_BINDING_RPC,
            OCT_ON_SET, NULL, NULL);

    err = oct_set_get(SET_SEQUENTIAL, barrier_record,
            "%s_ { barrier: '%s' }", name, name);
    err = oct_get_names(&names, &current_barriers, "_ { barrier: '%s' }",
            name);
    oct_free_names(names, current_barriers);
    if (err_is_fail(err)) {
        return err;
    }
    //debug_printf("current_barriers: %lu wait_for: %lu\n", current_barriers,
    //        wait_for);

    if (current_barriers != wait_for) {
        struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
        err = cl->call_seq.exists(cl, name, t, &tid, &exist_err);
        if (err_is_fail(err)) {
            return err;
        }
        err = exist_err;

        if (err_is_ok(err)) {
            // Barrier already exists
        }
        if (err_no(err) == OCT_ERR_NO_RECORD) {
            // Wait until barrier record is created
            err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
            free(record);
            assert(mode & OCT_REMOVED);

            err = SYS_ERR_OK;
        }
        else {
            // Some other error happend, return it
        }
    }
    else {
        // We are the last to enter the barrier,
        // wake up the others
        err = oct_set(name);
    }

    return err;
}
Ejemplo n.º 3
0
/**
 * \brief Leave a barrier. Blocks until all involved parties have
 * called oct_barrier_leave().
 *
 * Client deletes its barrier record. In case the client
 * was the last one we delete the special record which
 * wakes up all other clients.
 *
 * \param barrier_record Clients own record as provided by
 * oct_barrier_enter.
 */
errval_t oct_barrier_leave(const char* barrier_record)
{
    errval_t exist_err;
    errval_t err;
    char* rec_name = NULL;
    char* barrier_name = NULL;
    char* record = NULL;
    char** names = NULL;
    size_t remaining_barriers = 0;
    uint64_t mode = 0;
    uint64_t state = 0;
    uint64_t fn = 0;
    octopus_trigger_id_t tid;
    octopus_trigger_t t = oct_mktrigger(SYS_ERR_OK, octopus_BINDING_RPC,
            OCT_ON_DEL, NULL, NULL);

    //debug_printf("leaving: %s\n", barrier_record);
    err = oct_read(barrier_record, "%s { barrier: %s }", &rec_name,
            &barrier_name);
    if (err_is_ok(err)) {
        err = oct_del(rec_name);
        if (err_is_fail(err)) {
            goto out;
        }

        err = oct_get_names(&names, &remaining_barriers, "_ { barrier: '%s' }",
                barrier_name);
        oct_free_names(names, remaining_barriers);

        //debug_printf("remaining barriers is: %lu\n", remaining_barriers);

        if (err_is_ok(err)) {
            struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
            err = cl->call_seq.exists(cl, barrier_name, t, &tid, &exist_err);
            if (err_is_fail(err)) {
                goto out;
            }
            err = exist_err;

            if (err_is_ok(err)) {
                // Wait until everyone has left the barrier
                err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
                assert(mode & OCT_REMOVED);
            }
            else if (err_no(err) == OCT_ERR_NO_RECORD) {
                // barrier already deleted
                err = SYS_ERR_OK;
            }
        }
        else if (err_no(err) == OCT_ERR_NO_RECORD) {
            // We are the last one to leave the barrier,
            // wake-up all others
            err = oct_del("%s", barrier_name);
        }
        else {
            // Just return the error
        }
    }

out:
    free(record);
    free(rec_name);
    free(barrier_name);
    return err;
}