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