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