void _muxsendproc(void *v) { Muxqueue *q; void *p; Mux *mux; mux = v; q = _muxqalloc(); qlock(&mux->lk); mux->writeq = q; qlock(&mux->outlk); rwakeup(&mux->rpcfork); qunlock(&mux->lk); while((p = _muxqrecv(q)) != nil) if(mux->send(mux, p) < 0) break; qunlock(&mux->outlk); qlock(&mux->lk); _muxqhangup(q); while(_muxnbqrecv(q, &p)) free(p); free(q); mux->writeq = nil; rwakeup(&mux->rpcfork); qunlock(&mux->lk); return; }
/* * If you fork off two procs running muxrecvproc and muxsendproc, * then muxrecv/muxsend (and thus muxrpc) will never block except on * rendevouses, which is nice when it's running in one thread of many. */ void _muxrecvproc(void *v) { void *p; Mux *mux; Muxqueue *q; mux = v; q = _muxqalloc(); qlock(&mux->lk); mux->readq = q; qlock(&mux->inlk); rwakeup(&mux->rpcfork); qunlock(&mux->lk); while((p = mux->recv(mux)) != nil) if(_muxqsend(q, p) < 0){ free(p); break; } qunlock(&mux->inlk); qlock(&mux->lk); _muxqhangup(q); p = nil; while(_muxnbqrecv(q, &p) && p != nil){ free(p); p = nil; } free(q); mux->readq = nil; rwakeup(&mux->rpcfork); qunlock(&mux->lk); }
void fs_send(Queue *q, void *a) { int i, c; if(q == nil) panic("send null q"); if(!q->waitedfor) { for (i = 0; i < 5 && !q->waitedfor; i++) sleep(1000); if(!q->waitedfor) { /* likely a bug; don't wait forever */ print("no readers yet for %s q\n", q->name); abort(); } } qlock(q); while((c = q->count) >= q->size) rsleep(&q->full); i = q->loc + c; if(i >= q->size) i -= q->size; q->args[i] = a; q->count = c+1; rwakeup(&q->empty); /* no longer empty */ qunlock(q); }
/* * queue a lump & it's packet data for writing */ int queuewrite(Lump *u, Packet *p, int creator, uint ms) { LumpQueue *q; int i; trace(TraceProc, "queuewrite"); i = indexsect(mainindex, u->score); if(i < 0 || i >= nqs){ seterr(EBug, "internal error: illegal index section in queuewrite"); return -1; } q = &lumpqs[i]; qlock(&q->lock); while(q->r == ((q->w + 1) & (MaxLumpQ - 1))){ trace(TraceProc, "queuewrite sleep"); rsleep(&q->full); } q->q[q->w].u = u; q->q[q->w].p = p; q->q[q->w].creator = creator; q->q[q->w].ms = ms; q->q[q->w].gen = gen; q->w = (q->w + 1) & (MaxLumpQ - 1); trace(TraceProc, "queuewrite wakeup"); rwakeup(&q->empty); qunlock(&q->lock); return 0; }
void muxmsgandqlock(Mux *mux, void *p) { int tag; Muxrpc *r2; tag = mux->gettag(mux, p) - mux->mintag; /*print("mux tag %d\n", tag); */ qlock(&mux->lk); /* hand packet to correct sleeper */ if(tag < 0 || tag >= mux->mwait){ fprint(2, "%s: bad rpc tag %ux\n", argv0, tag); /* must leak packet! don't know how to free it! */ return; } r2 = mux->wait[tag]; if(r2 == nil || r2->prev == nil){ fprint(2, "%s: bad rpc tag %ux (no one waiting on that tag)\n", argv0, tag); /* must leak packet! don't know how to free it! */ return; } r2->p = p; dequeue(mux, r2); rwakeup(&r2->r); }
void spawnWaiter(Lock *l) { int pid; int64_t start; switch((pid = rfork(RFMEM|RFPROC|RFNOWAIT))) { case 0: /* wait for the alwaysLocked to be locked by the main process */ qlock(&rl); while(resInWaiter == 0xff) rsleep(&rStart); start = nsec(); resInWaiter = lockt(l, 6000); elapsedInWaiter = (nsec() - start) / (1000 * 1000); if(verbose) print("lockt returned %d, elapsed = %d ms\n", resInWaiter, elapsedInWaiter); rwakeup(&rCompleted); qunlock(&rl); exits(0); break; case -1: print("spawnWaiter: %r\n"); exits("rfork fails"); break; default: if(verbose) print("spawn waiter %d\n", pid); break; } }
void delaykickround(Round *r) { qlock(&r->lock); r->delaykick = 1; rwakeup(&r->delaywait); qunlock(&r->lock); }
static void puttag(VtConn *z, Rwait *r, int tag) { assert(z->wait[tag] == r); z->wait[tag] = nil; z->ntag--; rwakeup(&z->tagrend); }
void qclose(Queue *q) { qlock(&q->lk); q->closed = 1; rwakeup(&q->r); qunlock(&q->lk); }
int twflush(Fd *f) { dbg(DbgFdbuf, "twflush fd=%d\n", f->fd); qlock(&f->lk); rwakeup(&f->r); qunlock(&f->lk); return 0; }
int rwakeupall(Rendez *r) { int i; for(i=0; rwakeup(r); i++) ; return i; }
static void _kickround(Round *r, int wait) { int n; if(!r->doanother) trace(TraceProc, "kick %s", r->name); r->doanother = 1; rwakeup(&r->start); if(wait){ n = r->next; while((int)(n - r->last) > 0){ r->doanother = 1; rwakeup(&r->start); rsleep(&r->finish); } } }
static void puttag(Mux *mux, Muxrpc *r) { int i; i = r->tag - mux->mintag; assert(mux->wait[i] == r); mux->wait[i] = nil; mux->nwait--; mux->freetag = i; rwakeup(&mux->tagrend); free(r); }
void qwrite(Queue *q, Block *db, u32int bno) { qlock(&q->lk); while(q->nel == MAXQ) rsleep(&q->r); q->el[q->wi].db = db; q->el[q->wi].bno = bno; if(++q->wi == MAXQ) q->wi = 0; if(q->nel++ == MAXQ/2) rwakeup(&q->r); qunlock(&q->lk); }
void electmuxer(Mux *mux) { Muxrpc *rpc; /* if there is anyone else sleeping, wake them to mux */ for(rpc=mux->sleep.next; rpc != &mux->sleep; rpc = rpc->next){ if(!rpc->async){ mux->muxer = rpc; rwakeup(&rpc->r); return; } } mux->muxer = nil; }
int sendq(Queue *q, void *p) { Qel *e; e = emalloc(sizeof(Qel)); qlock(&q->lk); e->p = p; e->next = nil; if(q->head == nil) q->head = e; else q->tail->next = e; q->tail = e; rwakeup(&q->r); qunlock(&q->lk); return 0; }
static void queueproc(void *vq) { LumpQueue *q; Lump *u; Packet *p; int creator; uint ms; threadsetname("queueproc"); q = vq; for(;;){ qlock(&q->lock); while(q->w == q->r){ trace(TraceProc, "queueproc sleep empty"); rsleep(&q->empty); } u = q->q[q->r].u; p = q->q[q->r].p; creator = q->q[q->r].creator; ms = q->q[q->r].ms; q->r = (q->r + 1) & (MaxLumpQ - 1); trace(TraceProc, "queueproc wakeup flush"); rwakeupall(&q->flush); trace(TraceProc, "queueproc wakeup full"); rwakeup(&q->full); qunlock(&q->lock); trace(TraceProc, "queueproc writelump %V", u->score); if(writeqlump(u, p, creator, ms) < 0) fprint(2, "failed to write lump for %V: %r", u->score); trace(TraceProc, "queueproc wrotelump %V", u->score); putlump(u); } }
void backsumarena(Arena *arena) { ASum *as; if(sumwait.l == nil) return; as = MK(ASum); if(as == nil) return; qlock(&sumlock); as->arena = arena; as->next = nil; if(sumq) sumqtail->next = as; else sumq = as; sumqtail = as; rwakeup(&sumwait); qunlock(&sumlock); }
Block* qread(Queue *q, u32int *pbno) { Block *db; u32int bno; qlock(&q->lk); while(q->nel == 0 && !q->closed) rsleep(&q->r); if(q->nel == 0 && q->closed){ qunlock(&q->lk); return nil; } db = q->el[q->ri].db; bno = q->el[q->ri].bno; if(++q->ri == MAXQ) q->ri = 0; if(q->nel-- == MAXQ/2) rwakeup(&q->r); qunlock(&q->lk); *pbno = bno; return db; }
void* fs_recv(Queue *q, int) { void *a; int i, c; if(q == nil) panic("recv null q"); qlock(q); q->waitedfor = 1; while((c = q->count) <= 0) rsleep(&q->empty); i = q->loc; a = q->args[i]; i++; if(i >= q->size) i = 0; q->loc = i; q->count = c-1; rwakeup(&q->full); /* no longer full */ qunlock(q); return a; }
static void muxrpc(VtConn *z, Packet *p) { uchar tag, buf[2], *top; Rwait *r; if((top = packetpeek(p, buf, 0, 2)) == nil){ fprint(2, "libventi: short packet in vtrpc\n"); packetfree(p); return; } tag = top[1]; if((r = z->wait[tag]) == nil){ fprint(2, "libventi: unexpected packet tag %d in vtrpc\n", tag); abort(); packetfree(p); return; } r->p = p; r->done = 1; rwakeup(&r->r); }
Packet* _vtrpc(VtConn *z, Packet *p, VtFcall *tx) { int i; uchar tag, buf[2], *top; Rwait *r, *rr; /* must malloc because stack could be private */ r = vtmallocz(sizeof(Rwait)); qlock(&z->lk); r->r.l = &z->lk; tag = gettag(z, r); if(tx){ /* vtfcallrpc can't print packet because it doesn't have tag */ tx->tag = tag; if(chattyventi) fprint(2, "%s -> %F\n", argv0, tx); } /* slam tag into packet */ top = packetpeek(p, buf, 0, 2); if(top == nil){ packetfree(p); return nil; } if(top == buf){ werrstr("first two bytes must be in same packet fragment"); packetfree(p); vtfree(r); return nil; } top[1] = tag; qunlock(&z->lk); if(vtsend(z, p) < 0){ vtfree(r); return nil; } qlock(&z->lk); /* wait for the muxer to give us our packet */ r->sleeping = 1; z->nsleep++; while(z->muxer && !r->done) rsleep(&r->r); z->nsleep--; r->sleeping = 0; /* if not done, there's no muxer: start muxing */ if(!r->done){ if(z->muxer) abort(); z->muxer = 1; while(!r->done){ qunlock(&z->lk); if((p = vtrecv(z)) == nil){ werrstr("unexpected eof on venti connection"); z->muxer = 0; vtfree(r); return nil; } qlock(&z->lk); muxrpc(z, p); } z->muxer = 0; /* if there is anyone else sleeping, wake first unfinished to mux */ if(z->nsleep) for(i=0; i<256; i++){ rr = z->wait[i]; if(rr && rr->sleeping && !rr->done){ rwakeup(&rr->r); break; } } } p = r->p; puttag(z, r, tag); vtfree(r); qunlock(&z->lk); return p; }