|  | /* 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); | 
|  | } |