/* 检查Alt a是否可以被执行 */ static int altcanexec(Alt *a) { Altarray *ar; Channel *c; if(a->op == CHANNOP) return 0; c = a->c; if(c->bufsize == 0){ // 如果bufsize为0,则是通过发送接收队列共享数据的 // 获取发送or接收队列 ar = chanarray(c, otherop(a->op)); return ar && ar->n; }else{ switch(a->op){ default: return 0; case CHANSND: // 如果是发送的情况,查看buffer还有没有空间了 return c->nbuf < c->bufsize; case CHANRCV: // 如果是接收的情况,查看buffer还有没有数据 return c->nbuf > 0; } } }
/* a->op is Recv: 从对应得Channel的发送队列随机取出一个Alt, 并读取数据,Alt对应的Task可以进入就绪队列了 a->op is Send: 将数据拷贝到Buffer中 */ static void altexec(Alt *a) { int i; Altarray *ar; Alt *other; Channel *c; c = a->c; ar = chanarray(c, otherop(a->op)); if(ar && ar->n){ // 这里的逻辑目前看都是a->op == RECV才跑得到 i = rand()%ar->n; other = ar->a[i]; // a->v = other->v altcopy(a, other); // 将other从Channel的队列(接收队列)中删除 altalldequeue(other->xalt); other->xalt[0].xalt = other; // Task重新进入就绪队列 taskready(other->task); }else { // 将a->v的数据放到buffer里面 altcopy(a, nil); } }
static void altqueue(Alt *a) { Altarray *ar; ar = chanarray(a->c, a->op); addarray(ar, a); }
static void altexec(Alt *a) { int i; Altarray *ar; Alt *other; Channel *c; c = a->c; ar = chanarray(c, otherop(a->op)); if(ar && ar->n){ i = rand()%ar->n; other = ar->a[i]; altcopy(a, other); altalldequeue(other->xalt); other->xalt[0].xalt = other; taskready(other->task); }else altcopy(a, nil); }
static void altdequeue(Alt *a) { int i; Altarray *ar; ar = chanarray(a->c, a->op); if(ar == nil){ fprint(2, "bad use of altdequeue op=%d\n", a->op); abort(); } for(i=0; i<ar->n; i++) if(ar->a[i] == a){ delarray(ar, i); return; } fprint(2, "cannot find self in altdq\n"); abort(); }
static int altcanexec(Alt *a) { Altarray *ar; Channel *c; if(a->op == CHANNOP) return 0; c = a->c; if(c->bufsize == 0){ ar = chanarray(c, otherop(a->op)); return ar && ar->n; }else{ switch(a->op){ default: return 0; case CHANSND: return c->nbuf < c->bufsize; case CHANRCV: return c->nbuf > 0; } } }