Beispiel #1
0
static inline int
on_stack_accepting_up (wctx_t *ctx, int *accepting)
{
    cndfs_alg_local_t      *cloc = (cndfs_alg_local_t *) ctx->local;
    size_t                 *depth;
    int                     on_stack;
    on_stack = fset_find (cloc->pink, NULL, &ctx->state->ref, (void**)&depth, true);
    HREassert (on_stack != FSET_FULL);
    if (!on_stack) {
        *accepting = pins_state_is_accepting(ctx->model, state_info_state(ctx->state)) != 0;
        Debug ("Added state %zu %s with depth %zu accepting depth",
               ctx->state->ref, (*accepting ? "(accepting)" : ""), cloc->accepting_depth);
        *depth = cloc->accepting_depth; // write currect accepting depth
        cloc->accepting_depth += *accepting;
    }
    return on_stack;
}
Beispiel #2
0
int
cndfs_state_seen (void *ptr, transition_info_t *ti, ref_t ref, int seen)
{
    wctx_t             *ctx = (wctx_t *) ptr;
    cndfs_alg_local_t  *cloc = (cndfs_alg_local_t *) ctx->local;

    void               *level;
    if (!seen) {
        seen = fset_find (cloc->pink, NULL, &ref, &level, false);
        HREassert (seen != FSET_FULL);
    }
    if (seen) return 1;

    uint32_t old = state_store_get_colors (ref) & 3;

    return -(old == CCYAN);
    (void) ti;
}
Beispiel #3
0
static void
tarjan_handle (void *arg, state_info_t *successor, transition_info_t *ti,
               int seen)
{
    // parent state is ctx->state

    wctx_t             *ctx   = (wctx_t *) arg;
    alg_local_t        *loc   = ctx->local;
    raw_data_t         *addr;
    hash32_t            hash;
    int                 found;

    ctx->counters->trans++;

    // self-loop
    if (ctx->state->ref == successor->ref)
        return;

    // completed SCC
    if (state_store_has_color (successor->ref, SCC_STATE, 0))
        return;

    hash  = ref_hash (successor->ref);
    found = fset_find (loc->visited_states, &hash, &successor->ref,
                       (void **)&addr, false);

    if (found) {
        // previously visited state ==> update lowlink

        state_info_deserialize (loc->target, *addr);
        if (loc->state_tarjan.lowlink > loc->target_tarjan.lowlink)
            loc->state_tarjan.lowlink = loc->target_tarjan.lowlink;

    } else {
        // unseen state ==> push to search_stack

        raw_data_t stack_loc = dfs_stack_push (loc->search_stack, NULL);
        state_info_serialize (successor, stack_loc);
    }

    (void) ti; (void) seen;
}
Beispiel #4
0
static void
endfs_handle_red (void *arg, state_info_t *successor, transition_info_t *ti, int seen)
{
    wctx_t             *ctx = (wctx_t *) arg;
    alg_local_t        *loc = ctx->local;
    cndfs_alg_local_t  *cloc = (cndfs_alg_local_t *) ctx->local;
    int                 onstack;

    /* Find cycle back to the seed */
    HREassert (cloc->accepting_depth > 0);
    size_t             *level;
    onstack = ctx->state->ref == loc->seed->ref;
    if (!onstack) {
        onstack = fset_find (cloc->pink, NULL, &successor->ref, (void**)&level, false);
        HREassert (onstack != FSET_FULL);
    }

    if ( onstack && *level < cloc->accepting_depth )
        ndfs_report_cycle (ctx, ctx->model, loc->stack, successor);
    /* Mark states dangerous if necessary */
    if ( Strat_ENDFS == loc->strat &&
         pins_state_is_accepting(ctx->model, state_info_state(successor)) &&
         state_store_get_colors (successor->ref) != CRED )
        state_store_try_color(successor->ref, GDANGEROUS, loc->rec_bits);

    if ( !onstack && state_store_get_colors (successor->ref) != CRED ) {
        raw_data_t stack_loc = dfs_stack_push (loc->stack, NULL);
        state_info_serialize (successor, stack_loc);
    }

    // check proviso
    if (PINS_POR && proviso == Proviso_CNDFS && cloc->successors == NONEC) {
        if (ti->por_proviso != 0) { // state already fully expanded
            cloc->successors = SRCINV;
        } else if (onstack) { // cycle check
            if (onstack) cloc->successors = CYCLE;
        }
        // avoid full exploration (proviso is enforced later in backtrack)
        ti->por_proviso = 1; // avoid full exploration
    }
    (void) seen;
}
Beispiel #5
0
/**
 * move a search_stack state to the tarjan_stack
 */
static void
move_tarjan (wctx_t *ctx, state_info_t *state, raw_data_t state_data)
{
    alg_local_t        *loc   = ctx->local;
    raw_data_t         *addr;
    hash32_t            hash;
    int                 found;

    // add state to tarjan_stack
    raw_data_t tarjan_loc = dfs_stack_push (loc->tarjan_stack, NULL);
    state_info_serialize (state, tarjan_loc);

    // Update reference to the new stack
    hash  = ref_hash (state->ref);
    found = fset_find (loc->visited_states, &hash, &state->ref,
                       (void**) &addr, false);
    HREassert (*addr == state_data, "Wrong addr?");
    HREassert (found, "Could not find key in set");
    *addr = tarjan_loc;
}
Beispiel #6
0
static void
endfs_handle_blue (void *arg, state_info_t *successor, transition_info_t *ti, int seen)
{
    wctx_t             *ctx = (wctx_t *) arg;
    alg_local_t        *loc = ctx->local;
    cndfs_alg_local_t  *cloc = (cndfs_alg_local_t *) ctx->local;

    size_t             *level;
    int onstack = fset_find (cloc->pink, NULL, &successor->ref, (void**)&level, false);
    HREassert (onstack != FSET_FULL);

    /**
     * The following lines bear little resemblance to the algorithms in the
     * respective papers (Evangelista et al./ Laarman et al.), but we must
     * store all non-red states on the stack in order to calculate
     * all-red correctly later. Red states are also stored as optimization.
     */
    if ( ecd && onstack && *level < cloc->accepting_depth) {
        /* Found cycle in blue search */
        ndfs_report_cycle (ctx, ctx->model, loc->stack, successor);
    } else if ( all_red || (!onstack &&
                         state_store_get_colors (successor->ref) != CBLUE) ) {
        raw_data_t stack_loc = dfs_stack_push (loc->stack, NULL);
        state_info_serialize (successor, stack_loc);
    }

    // check proviso
    if (PINS_POR && proviso == Proviso_CNDFS && cloc->successors == NONEC) {
        if (ti->por_proviso != 0) { // state already fully expanded
            cloc->successors = SRCINV;
        } else if (onstack) { // check cycle
            cloc->successors = CYCLE;
        }
        // avoid full exploration (proviso is enforced later in backtrack)
        ti->por_proviso = 1;
    }
    (void) seen;
}
Beispiel #7
0
static int
resize (fset_t *dbs, fset_resize_t mode)
{
    void               *key, *data;
    bool                res;
    if (dbs->resizing) return true;
    dbs->resizing = 1;

    size_t              old_size = dbs->size;
    switch (mode) {
    case GROW:
        if (dbs->size == dbs->size_max) {
            dbs->resizing = 0;
            return false;
        }
        memset (dbs->hash + dbs->size, 0, sizeof (mem_hash_t[dbs->size]));
        dbs->size <<= 1;
        dbs->size3 <<= 1;
        break;
    case SHRINK:
        if (dbs->size == dbs->init_size) {
            dbs->resizing = 0;
            return true;
        }
        dbs->size >>= 1;
        dbs->size3 >>= 1;
        break;
    case REHASH: break;
    }
    dbs->mask = dbs->size - 1;
    Debug ("%s %zu to %zu", fset_resize_names[mode], old_size, dbs->size);

    //RTstartTimer (dbs->timer);
    size_t              tombs = 0;
    size_t              todos = 0;
    for (size_t i = 0; i < old_size; i++) {
        mem_hash_t          h = *memoized(dbs,i);
        if (TOMB == h) {
            tombs++;
            *memoized(dbs, i) = EMPTY;
        } else if (h != EMPTY) {// && home_loc(h) & dbs->mask != i) {
            dbs->todo[todos] = *memoized(dbs,i);
            void               *tdata = bucket(dbs, dbs->todo_data, todos);
            void               *data  = bucket(dbs, dbs->data, i);
            memcpy (tdata, data, dbs->total_length);
            todos++;
            *memoized(dbs, i) = EMPTY;
        }
    }
    dbs->tombs -= tombs;
    dbs->load  -= todos;
    HREassert (dbs->tombs == 0);

    for (size_t i = 0; i < todos; i++) {
        mem_hash_t          h = dbs->todo[i];
        key = bucket(dbs, dbs->todo_data, i);
        res = fset_find (dbs, &h, key, &data, true); // load++
        HREassert (!res);
        memcpy (data, key + dbs->key_length, dbs->data_length);
    }

    //RTstopTimer (dbs->timer);
    Debug ("%s %zu to %zu took %zu/%zu todos and cleaned %zu/%zu tombstones in %.2f sec",
           fset_resize_names[mode], old_size, dbs->size, todos, dbs->load, tombs,
           dbs->load + tombs, RTrealTime(dbs->timer));
    dbs->max_todos = max (todos, dbs->max_todos);
    dbs->max_grow = max (dbs->max_grow, dbs->size);
    dbs->resizes++;
    dbs->resizing = 0;
    return true;
}
Beispiel #8
0
void
tarjan_run (run_t *run, wctx_t *ctx)
{
    alg_local_t        *loc        = ctx->local;
    raw_data_t         *addr;
    raw_data_t          state_data;
    bool                on_stack;
    hash32_t            hash;

#ifdef HAVE_PROFILER
    Warning (info, "Using the profiler");
    ProfilerStart ("tarjan.perf");
#endif

#ifdef SEARCH_COMPLETE_GRAPH
    int              init_state = dlopen_get_worker_initial_state (ctx->id, W);
    int              inits      = 0;

    // loop until every state of the graph has been visited
    while ( 1 )
    {
        inits ++;
        // use loc->target as a dummy for the initial state
        loc->target->ref = init_state;
#endif

    tarjan_init (ctx);
    
    // continue until we are done exploring the graph
    while ( !run_is_stopped (run) ) {

        state_data = dfs_stack_top (loc->search_stack);

        if (state_data != NULL) {
            // there is a state on the current stackframe ==> explore it

            state_info_deserialize (ctx->state, state_data);

            // pop the state and continue if it is part of a completed SCC
            if (state_store_has_color (ctx->state->ref, SCC_STATE, 0)) {
                dfs_stack_pop (loc->search_stack);
                continue;
            }

            hash     = ref_hash (ctx->state->ref);
            on_stack = fset_find (loc->visited_states, &hash,
                                  &ctx->state->ref, (void **) &addr, true);

            if (!on_stack) {
                // unseen state ==> initialize and explore

                HREassert (loc->cnt.tarjan_counter != UINT32_MAX);
                loc->cnt.tarjan_counter ++;
                loc->state_tarjan.index   = loc->cnt.tarjan_counter;
                loc->state_tarjan.lowlink = loc->cnt.tarjan_counter;

                // point visited_states data to stack
                *addr = state_data;

                explore_state (ctx);

                state_info_serialize (ctx->state, state_data);

            } else {
                // previously visited state ==> update parent
                // NB: state is on tarjan_stack

                state_info_deserialize (ctx->state, *addr);
                update_parent (ctx, loc->state_tarjan.lowlink);
                dfs_stack_pop (loc->search_stack);
            }

        } else {
            // there is no state on the current stackframe ==> backtrack

            // we are done if we backtrack from the initial state
            if (0 == dfs_stack_nframes (loc->search_stack))
                break;

            // leave the stackframe
            dfs_stack_leave (loc->search_stack);
            ctx->counters->level_cur--;

            // retrieve the parent state from search_stack (to be removed)
            state_data = dfs_stack_top (loc->search_stack);
            state_info_deserialize (ctx->state, state_data);

            Debug ("Backtracking %zu (%d, %d)", ctx->state->ref,
                   loc->state_tarjan.index, loc->state_tarjan.lowlink);

            if (loc->state_tarjan.index == loc->state_tarjan.lowlink) {
                // index == lowlink ==> root of the SCC ==> report the SCC
                pop_scc (ctx, ctx->state->ref, loc->state_tarjan.lowlink);

            } else {
                // lowlink < index ==> LIVE SCC ==> move to tarjan_stack
                move_tarjan (ctx, ctx->state, state_data);
                update_parent (ctx, loc->state_tarjan.lowlink);
            }

            dfs_stack_pop (loc->search_stack);
        }
    }

#ifdef SEARCH_COMPLETE_GRAPH
        init_state = dlopen_get_new_initial_state (init_state);
        if (init_state == -1) {
            Warning(info, "Number of inits : %d", inits);
            break;
        }
    }
#endif

#ifdef HAVE_PROFILER
    Warning(info, "Done profiling");
    ProfilerStop();
#endif

    if (!run_is_stopped(run) && dfs_stack_size(loc->tarjan_stack) != 0)
        Warning (info, "Tarjan stack not empty: %zu (stack %zu)",
                 dfs_stack_size(loc->tarjan_stack),
                 dfs_stack_size(loc->search_stack));
    if (!run_is_stopped(run) && fset_count(loc->visited_states) != 0)
        Warning (info, "Stack-set not empty: %zu",
                 fset_count(loc->visited_states));
}
Beispiel #9
0
/* ENDFS dfs_red */
static void
endfs_red (wctx_t *ctx)
{
    alg_local_t        *loc = ctx->local;
    cndfs_alg_local_t  *cloc = (cndfs_alg_local_t *) ctx->local;
    size_t              seed_level = dfs_stack_nframes (loc->stack);
    int                 accepting = 0;
    int                 on_stack;
    size_t              count = fset_count(cloc->pink);

    size_t               *level;
    while ( !run_is_stopped(ctx->run) ) {
        raw_data_t          state_data = dfs_stack_top (loc->stack);
        if (NULL != state_data) {
            state_info_deserialize (ctx->state, state_data);

            // seed is only state on both cyan and pink stack
            on_stack = ctx->state->ref == loc->seed->ref;
            if (!on_stack) {
                on_stack = fset_find (cloc->pink, NULL, &ctx->state->ref, (void**)&level, false);
                HREassert (on_stack != FSET_FULL);
            }

            if (!on_stack && state_store_get_colors(ctx->state->ref) != CRED) {
                on_stack_accepting_up (ctx, &accepting); //add to stack

                bitvector_unset (&loc->stackbits, cur(ctx,INVOL));
                dfs_stack_push (cloc->in_stack, state_data);
                if ( Strat_CNDFS == loc->strat && ctx->state->ref != loc->seed->ref && accepting)
                    dfs_stack_push (cloc->out_stack, state_data);
                endfs_explore_state_red (ctx);
            } else {
                if (seed_level == dfs_stack_nframes (loc->stack))
                    break;
                dfs_stack_pop (loc->stack);
            }
        } else { //backtrack
            dfs_stack_leave (loc->stack);
            ctx->counters->level_cur--;
            /* exit search if backtrack hits seed, leave stack the way it was */
            if (seed_level == dfs_stack_nframes(loc->stack))
                break;

            state_data = dfs_stack_top (loc->stack);
            state_info_deserialize (ctx->state, state_data);

            if (check_cndfs_proviso(ctx)) {
                reach_explore_all (ctx, ctx->state);
                continue;
            }

            accepting = pins_state_is_accepting (ctx->model, state_info_state(ctx->state)) != 0;
            accepting_down (ctx, ctx->state, accepting);

            dfs_stack_pop (loc->stack);
        }
    }
    if (!run_is_stopped(ctx->run)) {
        HREassert (fset_count(cloc->pink) == count);
    }
}