145 lines · 1.9 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <venti.h>#include "queue.h" typedef struct Qel Qel;struct Qel{	Qel *next;	void *p;}; struct Queue{	int ref;	int hungup;	QLock lk;	Rendez r;	Qel *head;	Qel *tail;}; Queue*_vtqalloc(void){	Queue *q; 	q = vtmallocz(sizeof(Queue));	q->r.l = &q->lk;	q->ref = 1;	return q;} Queue*_vtqincref(Queue *q){	qlock(&q->lk);	q->ref++;	qunlock(&q->lk);	return q;} void_vtqdecref(Queue *q){	Qel *e;		qlock(&q->lk);	if(--q->ref > 0){		qunlock(&q->lk);		return;	}	assert(q->ref == 0);	qunlock(&q->lk); 	/* Leaks the pointers e->p! */	while(q->head){		e = q->head;		q->head = e->next;		free(e);	}	free(q);} int_vtqsend(Queue *q, void *p){	Qel *e; 	e = vtmalloc(sizeof(Qel));	qlock(&q->lk);	if(q->hungup){		werrstr("hungup queue");		qunlock(&q->lk);		return -1;	}	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;} void*_vtqrecv(Queue *q){	void *p;	Qel *e; 	qlock(&q->lk);	while(q->head == nil && !q->hungup)		rsleep(&q->r);	if(q->hungup){		qunlock(&q->lk);		return nil;	}	e = q->head;	q->head = e->next;	qunlock(&q->lk);	p = e->p;	vtfree(e);	return p;} void*_vtnbqrecv(Queue *q){	void *p;	Qel *e; 	qlock(&q->lk);	if(q->head == nil){		qunlock(&q->lk);		return nil;	}	e = q->head;	q->head = e->next;	qunlock(&q->lk);	p = e->p;	vtfree(e);	return p;} void_vtqhangup(Queue *q){	qlock(&q->lk);	q->hungup = 1;	rwakeupall(&q->r);	qunlock(&q->lk);}