]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cwfs/iobuf.c
merge
[plan9front.git] / sys / src / cmd / cwfs / iobuf.c
1 #include        "all.h"
2 #include        "io.h"
3
4 extern  long nhiob;
5 extern  Hiob *hiob;
6
7 Iobuf*
8 getbuf(Device *d, Off addr, int flag)
9 {
10         Iobuf *p, *s;
11         Hiob *hp;
12         Off h;
13
14         if(chatty > 1)
15                 print("getbuf %Z(%lld) f=%x\n", d, (Wideoff)addr, flag);
16         h = addr + (Off)(uintptr)d*1009;
17         if(h < 0)
18                 h = ~h;
19         h %= nhiob;
20         hp = &hiob[h];
21
22 loop:
23         lock(hp);
24
25 /*
26  * look for it in the active list
27  */
28         s = hp->link;
29         for(p=s;;) {
30                 if(p->addr == addr && p->dev == d) {
31                         if(p != s) {
32                                 p->back->fore = p->fore;
33                                 p->fore->back = p->back;
34                                 p->fore = s;
35                                 p->back = s->back;
36                                 s->back = p;
37                                 p->back->fore = p;
38                                 hp->link = p;
39                         }
40                         unlock(hp);
41                         qlock(p);
42                         if(p->addr != addr || p->dev != d || iobufmap(p) == 0) {
43                                 qunlock(p);
44                                 goto loop;
45                         }
46                         p->flags |= flag;
47                         return p;
48                 }
49                 p = p->fore;
50                 if(p == s)
51                         break;
52         }
53         if(flag & Bprobe) {
54                 unlock(hp);
55                 return 0;
56         }
57
58 /*
59  * not found
60  * take oldest unlocked entry in this queue
61  */
62 xloop:
63         p = s->back;
64         if(!canqlock(p)) {
65                 if(p == hp->link) {
66                         unlock(hp);
67                         fprint(2, "iobuf all locked\n");
68                         goto loop;
69                 }
70                 s = p;
71                 goto xloop;
72         }
73
74         /*
75          * its dangerous to flush the pseudo
76          * devices since they recursively call
77          * getbuf/putbuf. deadlock!
78          */
79         if(p->flags & Bres) {
80                 qunlock(p);
81                 if(p == hp->link) {
82                         unlock(hp);
83                         fprint(2, "iobuf all reserved\n");
84                         goto loop;
85                 }
86                 s = p;
87                 goto xloop;
88         }
89         if(p->flags & Bmod) {
90                 unlock(hp);
91                 if(iobufmap(p)) {
92                         if(!devwrite(p->dev, p->addr, p->iobuf))
93                                 p->flags &= ~(Bimm|Bmod);
94                         iobufunmap(p);
95                 }
96                 qunlock(p);
97                 goto loop;
98         }
99         hp->link = p;
100         p->addr = addr;
101         p->dev = d;
102         p->flags = flag;
103         unlock(hp);
104         if(iobufmap(p))
105                 if(flag & Brd) {
106                         if(!devread(p->dev, p->addr, p->iobuf))
107                                 return p;
108                         iobufunmap(p);
109                 } else
110                         return p;
111         else
112                 fprint(2, "iobuf cant map buffer %Z(%lld)\n", p->dev, (Wideoff)p->addr);
113         p->flags = 0;
114         p->dev = devnone;
115         p->addr = -1;
116         qunlock(p);
117         return 0;
118 }
119
120 /*
121  * syncblock tries to put out a block per hashline
122  * returns 0 all done,
123  * returns 1 if it missed something
124  */
125 int
126 syncblock(void)
127 {
128         Iobuf *p, *s, *q;
129         Hiob *hp;
130         long h;
131         int flag;
132
133         flag = 0;
134         for(h=0; h<nhiob; h++) {
135                 q = 0;
136                 hp = &hiob[h];
137                 lock(hp);
138                 s = hp->link;
139                 for(p=s;;) {
140                         if(p->flags & Bmod) {
141                                 if(q)
142                                         flag = 1;       /* more than 1 mod/line */
143                                 q = p;
144                         }
145                         p = p->fore;
146                         if(p == s)
147                                 break;
148                 }
149                 unlock(hp);
150                 if(q) {
151                         if(!canqlock(q)) {
152                                 flag = 1;               /* missed -- was locked */
153                                 continue;
154                         }
155                         if(!(q->flags & Bmod)) {
156                                 qunlock(q);
157                                 continue;
158                         }
159                         if(iobufmap(q)) {
160                                 if(!devwrite(q->dev, q->addr, q->iobuf))
161                                         q->flags &= ~(Bmod|Bimm);
162                                 iobufunmap(q);
163                         } else
164                                 flag = 1;
165                         qunlock(q);
166                 }
167         }
168         return flag;
169 }
170
171 void
172 sync(char *reason)
173 {
174         long i;
175
176         if(chatty)
177                 print("sync: %s\n", reason);
178         for(i=10*nhiob; i>0; i--)
179                 if(!syncblock())
180                         return;
181 }
182
183 void
184 putbuf(Iobuf *p)
185 {
186
187         if(canqlock(p))
188                 fprint(2, "buffer not locked %Z(%lld)\n", p->dev, (Wideoff)p->addr);
189         if(p->flags & Bimm) {
190                 if(!(p->flags & Bmod))
191                         fprint(2, "imm and no mod %Z(%lld)\n",
192                                 p->dev, (Wideoff)p->addr);
193                 if(!devwrite(p->dev, p->addr, p->iobuf))
194                         p->flags &= ~(Bmod|Bimm);
195         }
196         iobufunmap(p);
197         qunlock(p);
198 }
199
200 int
201 checktag(Iobuf *p, int tag, Off qpath)
202 {
203         Tag *t;
204         ulong pc;
205
206         qpath &= ~QPDIR;
207         t = (Tag*)(p->iobuf+BUFSIZE);
208         if((tag != t->tag) || ((qpath != QPNONE) && (qpath != t->path))){
209                 pc = getcallerpc(&p);
210
211                 if(qpath == QPNONE){
212                         fprint(2, "checktag pc=%lux %Z(%llux) tag/path=%G/%llud; expected %G\n",
213                                 pc, p->dev, (Wideoff)p->addr, t->tag, (Wideoff)t->path, tag);
214                 } else {
215                         fprint(2, "checktag pc=%lux %Z(%llux) tag/path=%G/%llud; expected %G/%llud\n",
216                                 pc, p->dev, (Wideoff)p->addr, t->tag, (Wideoff)t->path, tag, qpath);
217                 }
218                 return 1;
219         }       
220         return 0;
221 }
222
223 void
224 settag(Iobuf *p, int tag, long qpath)
225 {
226         Tag *t;
227
228         t = (Tag*)(p->iobuf+BUFSIZE);
229         t->tag = tag;
230         if(qpath != QPNONE)
231                 t->path = qpath & ~QPDIR;
232         p->flags |= Bmod;
233 }
234
235 int
236 qlmatch(QLock *q1, QLock *q2)
237 {
238
239         return q1 == q2;
240 }
241
242 int
243 iobufql(QLock *q)
244 {
245         Iobuf *p, *s;
246         Hiob *hp;
247         long h;
248
249         for(h=0; h<nhiob; h++) {
250                 hp = &hiob[h];
251                 lock(hp);
252                 s = hp->link;
253                 for(p=s;;) {
254                         if(qlmatch(q, p)) {
255                                 unlock(hp);
256                                 return 1;
257                         }
258                         p = p->fore;
259                         if(p == s)
260                                 break;
261                 }
262                 unlock(hp);
263         }
264         return 0;
265 }