]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libventi/queue.c
nusb: resolve endpoint id conflict with different input and output types
[plan9front.git] / sys / src / libventi / queue.c
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*
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*
35 _vtqincref(Queue *q)
36 {
37         qlock(&q->lk);
38         q->ref++;
39         qunlock(&q->lk);
40         return q;
41 }
42
43 void
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
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*
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*
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
130 _vtqhangup(Queue *q)
131 {
132         qlock(&q->lk);
133         q->hungup = 1;
134         rwakeupall(&q->r);
135         qunlock(&q->lk);
136 }