int mill_choose_wait(void) { struct mill_choose *uc = &mill_running->u_choose; struct mill_slist_item *it; struct mill_clause *cl = NULL; /* If there are clauses that are immediately available randomly choose one of them. */ if(uc->available > 0) { int chosen = uc->available == 1 ? 0 : (int)(random() % (uc->available)); for(it = mill_slist_begin(&uc->clauses); it; it = mill_slist_next(it)) { cl = mill_cont(it, struct mill_clause, chitem); if(!cl->available) continue; if(!chosen) break; --chosen; } struct mill_chan *ch = mill_getchan(cl->ep); if(cl->ep->type == MILL_SENDER) mill_enqueue(ch, cl->val); else mill_dequeue(ch, mill_valbuf(cl->cr, ch->sz)); mill_resume(mill_running, cl->idx); return mill_suspend(); }
/* Unblock a coroutine blocked in mill_choose_wait() function. It also cleans up the associated clause list. */ static void mill_choose_unblock(struct mill_clause *cl) { struct mill_slist_item *it; struct mill_clause *itcl; for(it = mill_slist_begin(&cl->cr->u_choose.clauses); it; it = mill_slist_next(it)) { itcl = mill_cont(it, struct mill_clause, chitem); if(!itcl->used) continue; mill_list_erase(&itcl->ep->clauses, &itcl->epitem); } mill_resume(cl->cr, cl->idx); }
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"); }