| /* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ | 
 | /* See COPYRIGHT */ | 
 |  | 
 | #include <u.h> | 
 | #include <libc.h> | 
 | #include <mux.h> | 
 |  | 
 | typedef struct Qel Qel; | 
 | struct Qel | 
 | { | 
 | 	Qel *next; | 
 | 	void *p; | 
 | }; | 
 |  | 
 | struct Muxqueue | 
 | { | 
 | 	int hungup; | 
 | 	QLock lk; | 
 | 	Rendez r; | 
 | 	Qel *head; | 
 | 	Qel *tail; | 
 | }; | 
 |  | 
 | Muxqueue* | 
 | _muxqalloc(void) | 
 | { | 
 | 	Muxqueue *q; | 
 |  | 
 | 	q = mallocz(sizeof(Muxqueue), 1); | 
 | 	if(q == nil) | 
 | 		return nil; | 
 | 	q->r.l = &q->lk; | 
 | 	return q; | 
 | } | 
 |  | 
 | int | 
 | _muxqsend(Muxqueue *q, void *p) | 
 | { | 
 | 	Qel *e; | 
 |  | 
 | 	e = malloc(sizeof(Qel)); | 
 | 	if(e == nil) | 
 | 		return -1; | 
 | 	qlock(&q->lk); | 
 | 	if(q->hungup){ | 
 | 		werrstr("hungup queue"); | 
 | 		qunlock(&q->lk); | 
 | 		free(e); | 
 | 		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* | 
 | _muxqrecv(Muxqueue *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; | 
 | 	free(e); | 
 | 	return p; | 
 | } | 
 |  | 
 | int | 
 | _muxnbqrecv(Muxqueue *q, void **vp) | 
 | { | 
 | 	void *p; | 
 | 	Qel *e; | 
 |  | 
 | 	qlock(&q->lk); | 
 | 	if(q->head == nil){ | 
 | 		qunlock(&q->lk); | 
 | 		*vp = nil; | 
 | 		return q->hungup; | 
 | 	} | 
 | 	e = q->head; | 
 | 	q->head = e->next; | 
 | 	qunlock(&q->lk); | 
 | 	p = e->p; | 
 | 	free(e); | 
 | 	*vp = p; | 
 | 	return 1; | 
 | } | 
 |  | 
 | void | 
 | _muxqhangup(Muxqueue *q) | 
 | { | 
 | 	qlock(&q->lk); | 
 | 	q->hungup = 1; | 
 | 	rwakeupall(&q->r); | 
 | 	qunlock(&q->lk); | 
 | } |