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