|
|
1.1 root 1: /*
2: * bio.c -- buffer handling code.
3: *
4: * This code REALLY assumes single-threaded execution. All locks are
5: * advisory only and may be revoked without notice.
6: *
7: * See also bread() in diskio.c.
8: */
9:
10: #include <sys/types.h>
11: #include <sys/buf.h>
12: #include <sys/stat.h>
13:
14: #include "tboot.h"
15:
16: #define NBUF 23 /* Number of disk buffers in cache. */
17:
18: static BUF bufl[NBUF]; /* Buffer structures. */
19:
20: static char blockp[NBUF * BLOCK]; /* The blocks themselves. */
21: static int buf_inited = (1==2); /* Has bufinit been called? */
22:
23:
24: /*
25: * Initialise buffer headers.
26: */
27: void
28: bufinit()
29: {
30: int i; /* Counter for buffer structures. */
31: BUF *bp; /* Handy pointer for buffer shorthand. */
32: paddr_t p; /* Physical memory of the buffers themselves. */
33:
34: sanity_check("Entering bufinit()");
35:
36: if (buf_inited) {
37: puts("\r\nbufinit() called too many times.\r\n");
38: puts("Harmlessly ignored.\r\n");
39: return;
40: }
41: buf_inited = (1==1);
42:
43: /* We're going to chop blockp up into disk buffers. */
44: p = (paddr_t) blockp;
45:
46: for (i = 0; i < NBUF; ++i) {
47: bp = &(bufl[i]); /* Shorthand... */
48: bp->b_dev = NODEV; /* Buffer is not associated with a device. */
49: bp->b_bno = (daddr_t) 0;
50: bp->b_paddr = p; /* Attach a physical buffer. */
51: sanity_check("bufinit() about to call gate_unlock()");
52: gate_unlock(bp->b_gate); /* Unlock the buffer. */
53:
54: p += BLOCK; /* Point to the next buffer. */
55: }
56: sanity_check("Leaving bufinit()");
57: } /* bufinit() */
58:
59:
60: /*
61: * Claim a buffer for a block.
62: * Finds the buffer if it has already been accessed, otherwise,
63: * picks another buffer.
64: */
65: BUF *
66: bclaim(block)
67: daddr_t block;
68: {
69: int i;
70: BUF *bp;
71: BUF *best_buf;
72:
73: /* Be sure to initialize buffers the first time. */
74: if (!buf_inited) {
75: bufinit();
76: }
77:
78: sanity_check("Start of bclaim");
79:
80: best_buf = (BUF *) NULL;
81:
82: /* Look to see if this block is cached. */
83: for (i = 0; i < NBUF; ++i) {
84: bp = &(bufl[i]);
85:
86: /* If this is exactly the buffer we want, grab it! */
87: if (block == bp->b_bno) {
88: #if 0
89: puts("!"); /* DEBUG buffer hit */
90: #endif /* 0 */
91: best_buf = bp;
92: }
93: }
94:
95: /*
96: * If we couldn't find an exact match--pick another one.
97: */
98: if ((BUF *) NULL == best_buf) {
99: #if 0
100: puts("?"); /* DEBUG buffer miss*/
101: #endif
102: sanity_check("About to call bpick()");
103: best_buf = bpick(1); /* Fetch a new block. */
104: sanity_check("bclaim() from bpick() to gate_unlock()");
105: }
106:
107: /* ASSERTION: At this point we have a buffer we can claim. */
108:
109:
110: gate_lock(best_buf->b_gate);
111:
112: sanity_check("Returning from bclaim()");
113: return(best_buf);
114: } /* bclaim() */
115:
116:
117: /*
118: * Pick the next buffer for allocation.
119: * Uses a round-robin scheme of buffer allocation, skipping over
120: * locked buffers. If all buffers are locked, they are forcibly
121: * unlocked and the first one is picked.
122: */
123: BUF *
124: bpick()
125: {
126: static int next_bp = NBUF;
127:
128: int i;
129:
130: BUF *retval;
131:
132: retval = (BUF *) NULL; /* Nothing found yet. */
133:
134: for (i = 0; ((BUF *)NULL == retval) && (i < NBUF); ++i) {
135: /* Wrap next_bp back to the beginning if needed. */
136: next_bp %= NBUF;
137:
138: /* If we've found an unlocked buffer, return it. */
139: if (!gate_locked(bufl[next_bp].b_gate)) {
140: /* Trash the contents. */
141: bufl[next_bp].b_dev = (dev_t) NODEV;
142: bufl[next_bp].b_bno = (daddr_t) 0;
143:
144: sanity_check("bpick().2");
145: retval = &(bufl[next_bp]);
146: }
147: ++next_bp;
148: }
149:
150: if ((BUF *)NULL == retval) {
151: buf_inited = FALSE; /* Force bufinit() to actually run. */
152: bufinit();
153: sanity_check("bpick().1");
154: retval = &(bufl[0]);
155: next_bp = 1;
156: }
157:
158: return(retval);
159: } /* bpick() */
160:
161:
162: /*
163: * Release a buffer for a block.
164: */
165: void
166: brelease(bp)
167: BUF *bp;
168: {
169:
170: /* Make sure the buffer is unlocked. */
171: sanity_check("brelease() about to call gate_unlock()");
172: gate_unlock(bp->b_gate);
173:
174: if (0 != (BFMOD & bp->b_flag)){
175: puts("Warning: I don't know how to brelease() a modified buffer.\r\n");
176: }
177: sanity_check("Returning from brelease()");
178: } /* brelease() */
179:
180:
181: /*
182: * Attempt to lock the gate 'g'.
183: * Return TRUE on success, FALSE if it was already locked.
184: */
185: int
186: gate_lock(g)
187: GATE g;
188: {
189: if (g[0]) {
190: return(FALSE);
191: }
192:
193: g[0] = TRUE;
194:
195: return(TRUE);
196: } /* gate_lock() */
197:
198:
199: /*
200: * Check to see if the gate 'g' is locked.
201: */
202: int
203: gate_locked(g)
204: GATE g;
205: {
206: return(g[0]? TRUE : FALSE);
207: } /* gate_locked() */
208:
209: /*
210: * Unlock the gate 'g'.
211: */
212: void
213: gate_unlock(g)
214: GATE g;
215: {
216:
217: sanity_check("Start of gate_unlock()");
218:
219: g[0] = FALSE;
220:
221: sanity_check("End of gate_unlock()");
222: } /* gate_unlock() */
223:
224: /*
225: * Sanity checker.
226: * Prints contents of "message" if something is amiss and dumps you
227: * into the monitor.
228: *
229: * Add tests and messages as needed.
230: */
231:
232: void
233: sanity_check(message)
234: char *message;
235: {
236: extern char sects, heads;
237: extern BUF bufl[];
238:
239: static int d_data_inited = FALSE; /* Is disk data inited? */
240: static uint16 osects; /* Correct number of sectors. */
241: static uint16 oheads; /* Correct number of heads. */
242:
243: int i;
244: static int paddr_ok_once = FALSE;
245: int paddr_ok;
246:
247: if (!d_data_inited) {
248: osects = sects;
249: oheads = heads;
250: d_data_inited = TRUE;
251: } else {
252: /* Test to see if disk information has been stomped on. */
253: if (osects != sects) {
254: puts(message);
255: puts(": dead sects.\r\n");
256: monitor();
257: }
258:
259: if (oheads != heads) {
260: puts(message);
261: puts(": dead heads.\r\n");
262: monitor();
263: }
264: }
265:
266:
267: /*
268: * Don't flunk this test until it has been passed once.
269: * Check to see if the b_paddr entries for buffers have
270: * been stomped on.
271: */
272: paddr_ok = TRUE;
273:
274: for (i = 0; i < NBUF; ++i) {
275: if (0 == (uint16) (bufl[i].b_paddr)) {
276: paddr_ok = FALSE; /* Test failed. */
277: break;
278: }
279: }
280:
281: if (paddr_ok) {
282: paddr_ok_once = TRUE;
283: } else if (paddr_ok_once) {
284: puts(message);
285: puts(": bad paddr in buffer.\r\n");
286: monitor();
287: }
288:
289: } /* sanity_check() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.