Beispiel #1
0
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;
}
Beispiel #2
0
/*
 * 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);
}
Beispiel #3
0
Datei: sub.c Projekt: npe9/harvey
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);
}
Beispiel #4
0
/*
 * 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;
}
Beispiel #5
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);
}
Beispiel #6
0
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;
	}
}
Beispiel #7
0
void
delaykickround(Round *r)
{
	qlock(&r->lock);
	r->delaykick = 1;
	rwakeup(&r->delaywait);
	qunlock(&r->lock);
}
Beispiel #8
0
static void
puttag(VtConn *z, Rwait *r, int tag)
{
	assert(z->wait[tag] == r);
	z->wait[tag] = nil;
	z->ntag--;
	rwakeup(&z->tagrend);
}
Beispiel #9
0
void
qclose(Queue *q)
{
	qlock(&q->lk);
	q->closed = 1;
	rwakeup(&q->r);
	qunlock(&q->lk);
}
Beispiel #10
0
Datei: fdbuf.c Projekt: bazil/tra
int
twflush(Fd *f)
{
	dbg(DbgFdbuf, "twflush fd=%d\n", f->fd);
	qlock(&f->lk);
	rwakeup(&f->r);
	qunlock(&f->lk);
	return 0;
}
Beispiel #11
0
int
rwakeupall(Rendez *r)
{
	int i;

	for(i=0; rwakeup(r); i++)
		;
	return i;
}
Beispiel #12
0
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);
		}
	}
}
Beispiel #13
0
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);
}
Beispiel #14
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
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);
	}
}
Beispiel #18
0
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);
}
Beispiel #19
0
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;
}
Beispiel #20
0
Datei: sub.c Projekt: npe9/harvey
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;
}
Beispiel #21
0
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);
}
Beispiel #22
0
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;
}