xref: /plan9-contrib/sys/src/cmd/9660srv/iobuf.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include "dat.h"
6 #include "fns.h"
7 
8 #define	NIOBUF		100
9 #define	HIOB		(NIOBUF/3)
10 
11 static Iobuf*	hiob[HIOB];		/* hash buckets */
12 static Iobuf	iobuf[NIOBUF];		/* buffer headers */
13 static Iobuf*	iohead;
14 static Iobuf*	iotail;
15 
16 Iobuf*
17 getbuf(Xdata *dev, long addr)
18 {
19 	Iobuf *p, *h, **l, **f;
20 
21 	l = &hiob[addr%HIOB];
22 	for(p = *l; p; p = p->next) {
23 		if(p->addr == addr && p->dev == dev) {
24 			p->busy++;
25 			return p;
26 		}
27 	}
28 
29 	/* Find a non-busy buffer from the tail */
30 	for(p = iotail; p && p->busy; p = p->prev)
31 		;
32 	if(p == 0)
33 		panic(0, "all buffers busy");
34 
35 	/* Delete from hash chain */
36 	f = &hiob[p->addr%HIOB];
37 	for(h = *f; h; h = h->next) {
38 		if(h == p) {
39 			*f = p->hash;
40 			break;
41 		}
42 		f = &h->hash;
43 	}
44 
45 	/* Hash and fill */
46 	p->hash = *l;
47 	*l = p;
48 	p->addr = addr;
49 	p->dev = dev;
50 	p->busy++;
51 	if(waserror()) {
52 		p->addr = 0;	/* stop caching */
53 		putbuf(p);
54 		nexterror();
55 	}
56 	xread(p);
57 	poperror();
58 	return p;
59 }
60 
61 void
62 putbuf(Iobuf *p)
63 {
64 	if(p->busy <= 0)
65 		panic(0, "putbuf");
66 
67 	p->busy--;
68 	if(p == iohead)
69 		return;
70 
71 	/* Link onto head for lru */
72 	if(p->prev)
73 		p->prev->next = p->next;
74 	else
75 		iohead = p->next;
76 
77 	if(p->next)
78 		p->next->prev = p->prev;
79 	else
80 		iotail = p->prev;
81 
82 	p->prev = 0;
83 	p->next = iohead;
84 	iohead->prev = p;
85 	iohead = p;
86 }
87 
88 void
89 purgebuf(Xdata *dev)
90 {
91 	Iobuf *p;
92 
93 	for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++)
94 		if(p->dev == dev)
95 			p->busy = 0;
96 
97 	/* Blow hash chains */
98 	memset(hiob, 0, sizeof(hiob));
99 }
100 
101 void
102 iobuf_init(void)
103 {
104 	Iobuf *p;
105 
106 	iohead = iobuf;
107 	iotail = iobuf+NIOBUF-1;
108 
109 	for(p = iobuf; p <= iotail; p++) {
110 		p->next = p+1;
111 		p->prev = p-1;
112 
113 		p->iobuf = sbrk(Sectorsize);
114 		if((long)p->iobuf == -1)
115 			panic(0, "iobuf_init");
116 	}
117 
118 	iohead->prev = 0;
119 	iotail->next = 0;
120 }
121