コード例 #1
0
ファイル: spec_utils.c プロジェクト: gitter-badger/ceptr
void visdump(Defs *defs,T *x) {
    if (G_visdump_count) {
        int *path = _t_get_path(x);
        _visdump(defs,x,path);
        free(path);
    }
}
コード例 #2
0
ファイル: accumulator.c プロジェクト: ChunHungLiu/ceptr
/**
 * clean shutdown of the the ceptr system
 *
 * should be called by the thread that called _a_boot() (or _a_start_vmhost())
 */
void _a_shut_down() {
    // cleanly close down any processing in the VM_Host
    __r_kill(G_vm->r);

    _v_join_thread(&G_vm->clock_thread);
    _v_join_thread(&G_vm->vm_thread);

    char fn[1000];

    // serialize the semtable
    __a_serializet(_t_root(G_vm->sem->stores[0].definitions),SEM_FN);

    int i;
    T *paths = _t_new_root(RECEPTOR_PATHS);
    for (i=0;i<G_vm->sem->contexts;i++) { // we don't need the path of the root so start at 1
        int *p = _t_get_path(G_vm->sem->stores[i].definitions);
        if (p) {
            _t_new(paths,RECEPTOR_PATH,p,sizeof(int)*(_t_path_depth(p)+1));
            free(p);
        }
        else
            _t_newr(paths,STRUCTURE_ANYTHING); // should be something like DELETED_CONTEXT
    }
    __a_serializet(paths,PATHS_FN);
    _t_free(paths);

    // serialize the receptor part of the vmhost
    void *surface;
    size_t length;
    _r_serialize(G_vm->r,&surface,&length);
    //    _r_unserialize(surface);
    __a_vmfn(fn,G_vm->dir);
    writeFile(fn,surface,length);
    free(surface);

    // serialize other parts of the vmhost
    H h = _m_newr(null_H,SYS_STATE);
    H har = _m_newr(h,ACTIVE_RECEPTORS);
    for (i=0;i<G_vm->active_receptor_count;i++) {
        _m_new(har,RECEPTOR_XADDR,&G_vm->active_receptors[i].x,sizeof(Xaddr));
    }
    S *s = _m_serialize(h.m);
    __a_vm_state_fn(fn,G_vm->dir);
    writeFile(fn,s,s->total_size);
    free(s);
    _m_free(h);

    // free the memory used by the SYS_RECEPTOR
    _v_free(G_vm);
    G_vm = NULL;
}
コード例 #3
0
ファイル: process.c プロジェクト: sourceops/ceptr
/**
 * reduce all the processes in a queue
 *
 * @param[in] q the queue to be processed
 */
Error _p_reduceq(Q *q) {
#ifdef debug_reduce
    printf("\n\nStarting reduce:\n");
#endif
    Qe *qe = q->active;
    Error next_state;
    struct timespec start, end;

    while (q->contexts_count) {

#ifdef debug_reduce
        R *context = qe->context;
        char *sn[]={"Ascend","Descend","Pushed","Pop","Eval","Block","Send","Done"};
        char *s = context->state <= 0 ? sn[-context->state -1] : "Error";
        printf("ID:%p -- State %s : %d\n",qe,s,context->state);
        printf("  idx:%d\n",context->idx);
        puts(_t2s(q->defs,context->run_tree));
        if (context) {
            if (context->node_pointer == 0) {
                printf("Node Pointer: NULL!\n");
            }
            else {
                printf("rt_cur_child:%d\n",rt_cur_child(context->node_pointer));
                int *path = _t_get_path(context->node_pointer);
                char pp[255];
                _t_sprint_path(path,pp);
                printf("Node Pointer:%s\n",pp);
                free(path);
            }
        }
        printf("\n");
#endif

        clock_gettime(CLOCK_MONOTONIC, &start);
        next_state = _p_step(q->defs, &qe->context); // next state is set in directly in the context
        clock_gettime(CLOCK_MONOTONIC, &end);
        qe->accounts.elapsed_time +=  diff_micro(&start, &end);

        Qe *next = qe->next;
        if (next_state == Done) {
            // remove from the round-robin
            __p_dequeue(q->active,qe);

            // add to the completed list
            __p_enqueue(q->completed,qe);
            q->contexts_count--;
        }
        else if (next_state == Block) {
            // remove from the round-robin
            __p_dequeue(q->active,qe);

            // add to the blocked list
            __p_enqueue(q->blocked,qe);
            q->contexts_count--;
        }
        else if (next_state == Send) {
            // remove from the round-robin
            __p_dequeue(q->active,qe);

            // take the signal off the run tree and send it, adding a send result in it's place
            T *signal = qe->context->node_pointer;
            T *parent = _t_parent(signal);

            //@todo figure out what that return value should be.  Probably some result from
            // the actual signal sending machinery, or at least what ever is going to
            // evaluate the destination address for validity.
            T *result = _t_newi(0,TEST_INT_SYMBOL,0);

            //@todo refactor this into a version of _t_replace that swaps out the given child and returns it
            // rather than freeing it.
            parent->structure.children[0] = result; // 0 is the first child
            result->structure.parent = parent;
            signal->structure.parent = NULL;

            _t_add(q->pending_signals,signal);

            // add to the blocked list
            __p_enqueue(q->blocked,qe);
            q->contexts_count--;
        }
        qe = next ? next : q->active;  // next in round robing or wrap
    };
    // @todo figure out what error we should be sending back here, i.e. what if
    // one process ended ok, but one did not.  What's the error?  Probably
    // the errors here would be at a different level, and the caller would be
    // expected to inspect the errors of the reduced processes.
    return 0;
}
コード例 #4
0
ファイル: process.c プロジェクト: sourceops/ceptr
/**
 * take one step in the execution state machine given a run-tree context
 *
 * a run_tree is expected to have a code tree as the first child, parameters as the second,
 * and optionally an error handling routine as the third child.
 *
 * @param[in] processes context of defined processes
 * @param[in] pointer to context pointer
 * @returns the next state that will be called for the context
 */
Error _p_step(Defs *defs, R **contextP) {
    R *context = *contextP;

    switch(context->state) {
    case noReductionErr:
    case Block:
    case Send:
        raise_error0("whoa, virtual states can't be executed!"); // shouldn't be calling step if Done or noErr or Block or Send
        break;
    case Pop:
        // if this was the successful reduction by an error handler
        // move the value to the 1st child
        if (context->err) {
            T *t = _t_detach_by_idx(context->run_tree,3);
            if (t) {
                _t_replace(context->run_tree,1,t);
                context->err = noReductionErr;
            }
        }

        // if this is top caller on the stack then we are completely done
        if (!context->caller) {
            context->state = Done;
            break;
        }
        else {
            // otherwise pop the context
            R *ctx = context;
            context = context->caller;  // set the new context

            if (!ctx->err) {
                // get results of the run_tree
                T *np = _t_detach_by_idx(ctx->run_tree,1);
                _t_replace(context->parent,context->idx,np); // replace the process call node with the result
                rt_cur_child(np) = RUN_TREE_EVALUATED;
                context->node_pointer = np;
                context->state = Eval;  // or possible ascend??
            }
            else context->state = ctx->err;
            // cleanup
            _t_free(ctx->run_tree);
            free(ctx);
            context->callee = 0;
            *contextP = context;
        }

        break;
    case Eval:
        {
            T *np = context->node_pointer;
            if (!np) {
                raise_error0("Whoa! Null node pointer");
            }
            Process s = _t_symbol(np);

            if (semeq(s,PARAM_REF)) {
                T *param = _t_get(context->run_tree,(int *)_t_surface(np));
                if (!param) {
                    raise_error0("request for non-existent param");
                }
                context->node_pointer = np = _t_rclone(param);
                _t_replace(context->parent, context->idx,np);
                s = _t_symbol(np);
            }
            // @todo what if the replaced parameter is itself a PARAM_REF tree ??

            // if this node is not a process, i.e. it's data, then we are done descending
            // and it will be the result so ascend
            if (!is_process(s)) {
                context->state = Ascend;
            }
            else {
                int c = _t_children(np);
                if (c == rt_cur_child(np) || semeq(s,QUOTE)) {
                    // if the current child == the child count this means
                    // all the children have been processed, so we can evaluate this process
                    // if the process is QUOTE that's a special case and we evaluate it
                    // immediately without descending.
                    if (!is_sys_process(s)) {
                        // if it's user defined process then we check the signature and then make
                        // a new run-tree run that process
                        Error e = __p_check_signature(defs,s,np);
                        if (e) context->state = e;
                        else {
                            T *run_tree = __p_make_run_tree(defs->processes,s,np);
                            context->state = Pushed;
                            *contextP = __p_make_context(run_tree,context);
                        }
                    }
                    else {
                        // if it's a sys process we can just reduce it in and then ascend
                        // or move to the error handling state
                        Error e = __p_reduce_sys_proc(context,s,np);
                        context->state = e ? e : Ascend;
                    }
                }
                else if(c) {
                    //descend and increment the current child we're working on!
                    context->state = Descend;
                }
                else {
                    raise_error0("whoa! brain fart!");
                }
            }
        }
        break;
    case Ascend:
        rt_cur_child(context->node_pointer) = RUN_TREE_EVALUATED;
        context->node_pointer = context->parent;
        context->parent = _t_parent(context->node_pointer);
        if (!context->parent || context->parent == context->run_tree) {
            context->idx = 1;
        }
        else context->idx = rt_cur_child(context->parent);
        if (context->node_pointer == context->run_tree)
            context->state = Pop;
        else
            context->state = Eval;
        break;
    case Descend:
        context->parent = context->node_pointer;
        context->idx = ++rt_cur_child(context->node_pointer);
        context->node_pointer = _t_child(context->node_pointer,context->idx);
        context->state = Eval;
        break;
    default:
        context->err = context->state;
        if (_t_children(context->run_tree) <= 2) {
            // no error handler so just return the error
            context->state = Pop;
        }
        else {
            // the first parameter to the error code is always a reduction error
            // which gets added on as the 4th child of the run tree when the
            // error happens.
            T *ps = _t_newr(context->run_tree,PARAMS);

            //@todo: fix this so we don't actually use an error value that
            // then has to be translated into a symbol, but rather so that we
            // can programatically calculate the symbol.
            Symbol se;
            switch(context->state) {
            case tooFewParamsReductionErr: se=TOO_FEW_PARAMS_ERR;break;
            case tooManyParamsReductionErr: se=TOO_MANY_PARAMS_ERR;break;
            case signatureMismatchReductionErr: se=SIGNATURE_MISMATCH_ERR;break;
            case notProcessReductionError: se=NOT_A_PROCESS_ERR;break;
            case notInSignalContextReductionError: se=NOT_IN_SIGNAL_CONTEXT_ERR;
            case divideByZeroReductionErr: se=ZERO_DIVIDE_ERR;break;
            case incompatibleTypeReductionErr: se=INCOMPATIBLE_TYPE_ERR;break;
            case raiseReductionErr:
                se = *(Symbol *)_t_surface(_t_child(context->node_pointer,1));
                break;
            default: raise_error("unknown reduction error: %d",context->state);
            }
            T *err = __t_new(ps,se,0,0,sizeof(rT));
            int *path = _t_get_path(context->node_pointer);
            _t_new(err,ERROR_LOCATION,path,sizeof(int)*(_t_path_depth(path)+1));
            free(path);

            // switch the node_pointer to the top of the error handling routine
            context->node_pointer = _t_child(context->run_tree,3);
            context->idx = 3;
            context->parent = context->run_tree;

            context->state = Eval;
        }
    }
    return context->state;
}