|
|
1.1 ! root 1: /* ! 2: * Virtual memory system for Coherent. ! 3: */ ! 4: #include "misc.h" ! 5: #include <sys/stat.h> ! 6: ! 7: #define FILES 20 ! 8: #define VBLKB 9 /* bytes in virtual block as a power of 2 */ ! 9: #define VBLK (1 << VBLKB) /* bytes in a virtual block */ ! 10: ! 11: struct mapper { ! 12: unsigned dirty:1; ! 13: unsigned what_in:15; ! 14: }; ! 15: static unsigned long limit[20]; ! 16: static unsigned long initp; ! 17: static unsigned topf; ! 18: static struct mapper *map; ! 19: static char *data; ! 20: static unsigned blocks; ! 21: static int tmp, ramsw; ! 22: static struct stat st; ! 23: ! 24: /* ! 25: * init virtual system. ! 26: * Called with work file name, may be /dev/ram1, and the ! 27: * approximate amount of storage to be used for buffers. ! 28: * The more you give it the better it works. ! 29: */ ! 30: void ! 31: vinit(fname, ram) ! 32: char *fname; /* file name of virtual device e.g. /dev/rram1 */ ! 33: unsigned ram; /* amount of storage to devote to ram */ ! 34: { ! 35: if(!(blocks = ram / (VBLK + sizeof(*map)))) ! 36: fatal("Virtual; workspace too small"); ! 37: data = alloc(blocks << VBLKB); ! 38: map = (struct mapper *)alloc(blocks * sizeof(*map)); ! 39: ramsw = topf = initp = 0; /* make code reusable */ ! 40: ! 41: if((0 == stat(fname, &st)) && (st.st_mode & S_IFCHR)) { ! 42: switch(is_fs(fname)) { ! 43: case -1: ! 44: fatal("Virtual; cannot seek %s", fname); ! 45: case 1: ! 46: fatal("Virtual; %s has a file system", fname); ! 47: case 0: ! 48: if(!strcmp(fname, "/dev/ram1")) ! 49: ramsw = 1; ! 50: if(-1 == (tmp = open(fname, 2))) ! 51: fatal("Virtual; cannot open(%s, 2)", fname); ! 52: } ! 53: return; ! 54: } ! 55: ! 56: if(-1 == (tmp = creat(fname, 0600))) ! 57: fatal("Virtual; cannot creat(%s, 0600)", fname); ! 58: close(tmp); ! 59: if(-1 == (tmp = open(fname, 2))) ! 60: fatal("Virtual; cannot open(%s, 2)", fname); ! 61: unlink(fname); ! 62: fstat(tmp, &st); ! 63: } ! 64: ! 65: /* ! 66: * Close down virtual system and free it's space ! 67: */ ! 68: void ! 69: vshutDown() ! 70: { ! 71: close(tmp); ! 72: if(ramsw) ! 73: close(open("/dev/ram1close", 0)); ! 74: free(map); ! 75: free(data); ! 76: } ! 77: ! 78: /* ! 79: * Set up a virtual file. Say you want to emulate having a ! 80: * 100000 byte array and a 50000 byte array with virtual. ! 81: * vid1 = vopen(100000L); vid2 = vopen(50000L); ! 82: */ ! 83: unsigned ! 84: vopen(vamt) ! 85: unsigned long vamt; ! 86: { ! 87: if(topf == FILES) ! 88: fatal("Too many vopen calls"); ! 89: vamt = limit[topf + 1] = limit[topf] + vamt; ! 90: topf++; ! 91: vamt >>= VBLKB; ! 92: vamt /= blocks; /* must fit in 15 bits */ ! 93: if(vamt > 0x7fff) ! 94: fatal("Virtual; too much virtual space for buffers"); ! 95: ! 96: if(st.st_mode & S_IFCHR) { /* character special file */ ! 97: char work[VBLK]; ! 98: ! 99: memset(work, 0, VBLK); ! 100: for(; initp < limit[topf]; initp += VBLK) ! 101: if(VBLK != write(tmp, work, VBLK)) ! 102: fatal("Virtual; error writing to tmp file"); ! 103: } ! 104: return(topf - 1); ! 105: } ! 106: ! 107: /* ! 108: * Find a character on the virtual system ! 109: * mark the blocks dirty bit if Find is to write. ! 110: * Given the example in the vopen() comment. If you want to ! 111: * find the 1000 th byte in vid1 ! 112: * c = vfind(vid1, 1000L, 0); ! 113: * To change the 2000 th byte in vid2 ! 114: * *(vfind(vid2, 2000L, 1)) = d; ! 115: */ ! 116: char * ! 117: vfind(vid, disp, dirty) ! 118: unsigned vid; /* virtual file no */ ! 119: unsigned long disp; /* where */ ! 120: int dirty; /* 1 if character gotten to write */ ! 121: { ! 122: unsigned which, what_in, byte_no; ! 123: unsigned long diskad; ! 124: char *where; ! 125: ! 126: if(vid >= topf) ! 127: fatal("Virtual; invalid vfile"); ! 128: if((disp += limit[vid]) >= limit[vid + 1]) ! 129: fatal("Virtual; request out of limits"); ! 130: ! 131: byte_no = disp & (VBLK - 1); ! 132: disp >>= VBLKB; ! 133: which = disp % blocks; ! 134: what_in = disp / blocks; ! 135: where = data + (which << VBLKB); ! 136: ! 137: if((diskad = map[which].what_in) != what_in) { ! 138: if(map[which].dirty) { ! 139: diskad *= blocks; ! 140: diskad += which; ! 141: diskad <<= VBLKB; ! 142: if(-1 == lseek(tmp, diskad, 0)) ! 143: fatal("Virtual; error in seek"); ! 144: if(VBLK != write(tmp, where, VBLK)) ! 145: fatal("Virtual; error in write"); ! 146: } ! 147: map[which].dirty = 0; /* clean */ ! 148: map[which].what_in = diskad = what_in; ! 149: diskad *= blocks; ! 150: diskad += which; ! 151: diskad <<= VBLKB; ! 152: if(-1 == lseek(tmp, diskad, 0)) ! 153: fatal("Virtual; error in seek"); ! 154: if(VBLK != read(tmp, where, VBLK)) ! 155: if(st.st_mode & S_IFCHR) /* char special device */ ! 156: fatal("Virtual; error in read"); ! 157: else ! 158: memset(where, 0, VBLK); ! 159: } ! 160: map[which].dirty |= dirty; /* maybe dirty */ ! 161: return(where + byte_no); ! 162: } ! 163: ! 164: #ifdef TEST ! 165: static int vid[FILES]; ! 166: static long lim[FILES]; ! 167: static char buf[80]; ! 168: ! 169: main() ! 170: { ! 171: char c, d; ! 172: int i, f; ! 173: long atol(); ! 174: long l, t, tests; ! 175: ! 176: vinit("/dev/ram1", atoi(ask(buf, "How much ram to reserve"))); ! 177: f = atol(ask(buf, "How many virtual files?")); ! 178: for(i = 0; i < f; i++) ! 179: vid[i] = vopen(lim[i] = atol(ask(buf, "How big is file %d", i))); ! 180: tests = atol(ask(buf, "How many tests?")); ! 181: srandl(100L, 100L); ! 182: for(t = 0; t < tests; t++) { /* set random locs */ ! 183: i = randl() % f; /* pick virtual file */ ! 184: l = randl() % lim[i]; /* pick location */ ! 185: c = i ^ l; ! 186: *(vfind(vid[i], l, 1)) = c; ! 187: } ! 188: srandl(100L, 100L); ! 189: for(t = 0; t < tests; t++) { /* test same random locs */ ! 190: i = randl() % f; /* pick virtual file */ ! 191: l = randl() % lim[i]; /* pick location */ ! 192: c = i ^ l; ! 193: if((d = *(vfind(vid[i], l, 0))) != c) ! 194: fatal("Expected %c got %c", c, d); ! 195: } ! 196: vshutDown(); ! 197: } ! 198: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.