1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 #include "queue.h" 5 6 typedef struct Qel Qel; 7 struct Qel 8 { 9 Qel *next; 10 void *p; 11 }; 12 13 struct Queue 14 { 15 int ref; 16 int hungup; 17 QLock lk; 18 Rendez r; 19 Qel *head; 20 Qel *tail; 21 }; 22 23 Queue* _vtqalloc(void)24_vtqalloc(void) 25 { 26 Queue *q; 27 28 q = vtmallocz(sizeof(Queue)); 29 q->r.l = &q->lk; 30 q->ref = 1; 31 return q; 32 } 33 34 Queue* _vtqincref(Queue * q)35_vtqincref(Queue *q) 36 { 37 qlock(&q->lk); 38 q->ref++; 39 qunlock(&q->lk); 40 return q; 41 } 42 43 void _vtqdecref(Queue * q)44_vtqdecref(Queue *q) 45 { 46 Qel *e; 47 48 qlock(&q->lk); 49 if(--q->ref > 0){ 50 qunlock(&q->lk); 51 return; 52 } 53 assert(q->ref == 0); 54 qunlock(&q->lk); 55 56 /* Leaks the pointers e->p! */ 57 while(q->head){ 58 e = q->head; 59 q->head = e->next; 60 free(e); 61 } 62 free(q); 63 } 64 65 int _vtqsend(Queue * q,void * p)66_vtqsend(Queue *q, void *p) 67 { 68 Qel *e; 69 70 e = vtmalloc(sizeof(Qel)); 71 qlock(&q->lk); 72 if(q->hungup){ 73 werrstr("hungup queue"); 74 qunlock(&q->lk); 75 return -1; 76 } 77 e->p = p; 78 e->next = nil; 79 if(q->head == nil) 80 q->head = e; 81 else 82 q->tail->next = e; 83 q->tail = e; 84 rwakeup(&q->r); 85 qunlock(&q->lk); 86 return 0; 87 } 88 89 void* _vtqrecv(Queue * q)90_vtqrecv(Queue *q) 91 { 92 void *p; 93 Qel *e; 94 95 qlock(&q->lk); 96 while(q->head == nil && !q->hungup) 97 rsleep(&q->r); 98 if(q->hungup){ 99 qunlock(&q->lk); 100 return nil; 101 } 102 e = q->head; 103 q->head = e->next; 104 qunlock(&q->lk); 105 p = e->p; 106 vtfree(e); 107 return p; 108 } 109 110 void* _vtnbqrecv(Queue * q)111_vtnbqrecv(Queue *q) 112 { 113 void *p; 114 Qel *e; 115 116 qlock(&q->lk); 117 if(q->head == nil){ 118 qunlock(&q->lk); 119 return nil; 120 } 121 e = q->head; 122 q->head = e->next; 123 qunlock(&q->lk); 124 p = e->p; 125 vtfree(e); 126 return p; 127 } 128 129 void _vtqhangup(Queue * q)130_vtqhangup(Queue *q) 131 { 132 qlock(&q->lk); 133 q->hungup = 1; 134 rwakeupall(&q->r); 135 qunlock(&q->lk); 136 } 137