Ejemplo n.º 1
0
void mill_chclose(chan ch) {
    if(mill_slow(!ch))
        mill_panic("null channel used");
    assert(ch->refcount > 0);
    --ch->refcount;
    if(ch->refcount)
        return;
    if(!mill_list_empty(&ch->sender.clauses) ||
          !mill_list_empty(&ch->receiver.clauses))
        mill_panic("attempt to close a channel while it is still being used");
    free(ch);
}
Ejemplo n.º 2
0
void mill_choose_out(void *clause, chan ch, void *val, size_t sz, int idx) {
    if(mill_slow(!ch))
        mill_panic("null channel used");
    if(mill_slow(ch->done))
        mill_panic("send to done-with channel");
    if(mill_slow(ch->sz != sz))
        mill_panic("send of a type not matching the channel");
    /* Find out whether the clause is immediately available. */
    int available = !mill_list_empty(&ch->receiver.clauses) ||
        ch->items < ch->bufsz ? 1 : 0;
    if(available)
        ++mill_running->u_choose.available;
    /* If there are available clauses don't bother with non-available ones. */
    if(!available && mill_running->u_choose.available)
        return;
    /* Fill in the clause entry. */
    struct mill_clause *cl = (struct mill_clause*) clause;
    cl->cr = mill_running;
    cl->ep = &ch->sender;
    cl->val = val;
    cl->available = available;
    cl->idx = idx;
    cl->used = 1;
    mill_slist_push_back(&mill_running->u_choose.clauses, &cl->chitem);
    if(cl->ep->seqnum == mill_choose_seqnum) {
        ++cl->ep->refs;
        return;
    }
    cl->ep->seqnum = mill_choose_seqnum;
    cl->ep->refs = 1;
    cl->ep->tmp = -1;
}
Ejemplo n.º 3
0
int mill_timer_next(void) {
    if(mill_list_empty(&mill_timers))
        return -1;
    int64_t nw = now();
    int64_t expiry = mill_cont(mill_list_begin(&mill_timers),
                               struct mill_timer, item)->expiry;
    return (int) (nw >= expiry ? 0 : expiry - nw);
}
Ejemplo n.º 4
0
int mill_timer_fire(void) {
    /* Avoid getting current time if there are no timers anyway. */
    if(mill_list_empty(&mill_timers))
        return 0;
    int64_t nw = now();
    int fired = 0;
    while(!mill_list_empty(&mill_timers)) {
        struct mill_timer *tm = mill_cont(
                                          mill_list_begin(&mill_timers), struct mill_timer, item);
        if(tm->expiry > nw)
            break;
        mill_list_erase(&mill_timers, mill_list_begin(&mill_timers));
        if(tm->callback)
            tm->callback(tm);
        fired = 1;
    }
    return fired;
}
Ejemplo n.º 5
0
/* Push new item to the channel. */
static void mill_enqueue(chan ch, void *val) {
    /* If there's a receiver already waiting, let's resume it. */
    if(!mill_list_empty(&ch->receiver.clauses)) {
        struct mill_clause *cl = mill_cont(
            mill_list_begin(&ch->receiver.clauses), struct mill_clause, epitem);
        memcpy(mill_valbuf(cl->cr, ch->sz), val, ch->sz);
        mill_choose_unblock(cl);
        return;
    }
    /* Write the value to the buffer. */
    assert(ch->items < ch->bufsz);
    size_t pos = (ch->first + ch->items) % ch->bufsz;
    memcpy(((char*)(ch + 1)) + (pos * ch->sz) , val, ch->sz);
    ++ch->items;
}
Ejemplo n.º 6
0
Archivo: debug.c Proyecto: 8l/libmill
void goredump(void) {
    char buf[256];
    char idbuf[10];

    fprintf(stderr,
        "\nCOROUTINE  state                                      "
        "current                                  created\n");
    fprintf(stderr,
        "----------------------------------------------------------------------"
        "--------------------------------------------------\n");
    struct mill_list_item *it;
    for(it = mill_list_begin(&mill_all_crs); it; it = mill_list_next(it)) {
        struct mill_cr *cr = mill_cont(it, struct mill_cr, debug.item);
        switch(cr->state) {
        case MILL_READY:
            sprintf(buf, "%s", mill_running == cr ? "RUNNING" : "ready");
            break;
        case MILL_MSLEEP:
            sprintf(buf, "msleep()");
            break;
        case MILL_FDWAIT:
            sprintf(buf, "fdwait(%d)", -1);
            break;
        case MILL_CHR:
        case MILL_CHS:
        case MILL_CHOOSE:
            {
                int pos = 0;
                if(cr->state == MILL_CHR)
                    pos += sprintf(&buf[pos], "chr(");
                else if(cr->state == MILL_CHS)
                    pos += sprintf(&buf[pos], "chs(");
                else
                    pos += sprintf(&buf[pos], "choose(");
                int first = 1;
                struct mill_slist_item *it;
                for(it = mill_slist_begin(&cr->u_choose.clauses); it;
                      it = mill_slist_next(it)) {
                if(first)
                    first = 0;
                else
                    pos += sprintf(&buf[pos], ",");
                pos += sprintf(&buf[pos], "<%d>", mill_getchan(
                        mill_cont(it, struct mill_clause,
                        chitem)->ep)->debug.id);
            }
            sprintf(&buf[pos], ")");
            }
            break;
        default:
            assert(0);
        }
        snprintf(idbuf, sizeof(idbuf), "{%d}", (int)cr->debug.id);
        fprintf(stderr, "%-8s   %-42s %-40s %s\n",
            idbuf,
            buf,
            cr == mill_running ? "---" : cr->debug.current,
            cr->debug.created ? cr->debug.created : "<main>");
    }
    fprintf(stderr,"\n");

    if(mill_list_empty(&mill_all_chans))
        return;
    fprintf(stderr,
        "CHANNEL  msgs/max    senders/receivers                          "
        "refs  done  created\n");
    fprintf(stderr,
        "----------------------------------------------------------------------"
        "--------------------------------------------------\n");
    for(it = mill_list_begin(&mill_all_chans); it; it = mill_list_next(it)) {
        struct mill_chan *ch = mill_cont(it, struct mill_chan, debug.item);
        snprintf(idbuf, sizeof(idbuf), "<%d>", (int)ch->debug.id);
        sprintf(buf, "%d/%d",
            (int)ch->items,
            (int)ch->bufsz);
        fprintf(stderr, "%-8s %-11s ",
            idbuf,
            buf);
        int pos;
        struct mill_list *clauselist;
        if(!mill_list_empty(&ch->sender.clauses)) {
            pos = sprintf(buf, "s:");
            clauselist = &ch->sender.clauses;
        }
        else if(!mill_list_empty(&ch->receiver.clauses)) {
            pos = sprintf(buf, "r:");
            clauselist = &ch->receiver.clauses;
        }
        else {
            sprintf(buf, " ");
            clauselist = NULL;
        }
        struct mill_clause *cl = NULL;
        if(clauselist)
            cl = mill_cont(mill_list_begin(clauselist),
                struct mill_clause, epitem);
        int first = 1;
        while(cl) {
            if(first)
                first = 0;
            else
                pos += sprintf(&buf[pos], ",");
            pos += sprintf(&buf[pos], "{%d}", (int)cl->cr->debug.id);
            cl = mill_cont(mill_list_next(&cl->epitem),
                struct mill_clause, epitem);
        }
        fprintf(stderr, "%-42s %-5d %-5s %s\n",
            buf,
            (int)ch->refcount,
            ch->done ? "yes" : "no",
            ch->debug.created);
    }
    fprintf(stderr,"\n");
}