|
|
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.