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