Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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