|
|
1.1 root 1: /* vmmem.c 4.7 81/07/09 */
2:
3: #include "sys/param.h"
4: #include "sys/systm.h"
5: #include "sys/pte.h"
6: #include "sys/cmap.h"
7: #include "sys/user.h"
8: #include "sys/proc.h"
9: #include "sys/text.h"
10: #include "sys/vm.h"
11: #include "sys/buf.h"
12: #include "sys/map.h"
13:
14: /*
15: * Shared text pages are not totally abandoned when a process
16: * exits, but are remembered while in the free list hashed by <mdev,blkno>
17: * off the cmhash structure so that they can be reattached
18: * if another instance of the program runs again soon.
19: */
20: #define CMHSIZ 512 /* SHOULD BE DYNAMIC */
21: #define CMHASH(bn) ((bn)&(CMHSIZ-1))
22: int cmhash[CMHSIZ]; /* make words big enough for c_hlink */
23:
24: /*
25: * Allocate memory, and always succeed
26: * by jolting page-out daemon
27: * so as to obtain page frames.
28: * To be used in conjunction with vmemfree().
29: */
30: vmemall(pte, size, p, type)
31: register struct pte *pte;
32: int size;
33: struct proc *p;
34: {
35: register int m;
36:
37: if (size <= 0 || size > maxmem)
38: panic("vmemall size");
39: while (size > 0) {
40: if (freemem < desfree)
41: wakeup((caddr_t)&proc[PAGEPID]); /* jolt daemon */
42: while (freemem == 0)
43: sleep((caddr_t)&freemem, PSWP+2);
44: m = imin(size, freemem);
45: (void) memall(pte, m, p, type);
46: size -= m;
47: pte += m;
48: }
49: if (freemem < desfree)
50: wakeup((caddr_t)&proc[PAGEPID]); /* jolt daemon */
51: /*
52: * Always succeeds, but return success for
53: * vgetu and vgetpt (e.g.) which call either
54: * memall or vmemall depending on context.
55: */
56: return (1);
57: }
58:
59: /*
60: * Free valid and reclaimable page frames belonging to the
61: * count pages starting at pte. If a page is valid
62: * or reclaimable and locked (but not a system page), then
63: * we simply mark the page as c_gone and let the pageout
64: * daemon free the page when it is through with it.
65: * If a page is reclaimable, and already in the free list, then
66: * we mark the page as c_gone, and (of course) don't free it.
67: *
68: * Determines the largest contiguous cluster of
69: * valid pages and frees them in one call to memfree.
70: */
71: vmemfree(pte, count)
72: register struct pte *pte;
73: register int count;
74: {
75: register struct cmap *c;
76: register struct pte *spte;
77: register int j;
78: int size, pcnt;
79:
80: if (count % CLSIZE)
81: panic("vmemfree");
82: for (size = 0, pcnt = 0; count > 0; pte += CLSIZE, count -= CLSIZE) {
83: if (pte->pg_fod == 0 && pte->pg_pfnum) {
84: c = &cmap[pgtocm(pte->pg_pfnum)];
85: pcnt += CLSIZE;
86: if (c->c_lock && c->c_type != CSYS) {
87: for (j = 0; j < CLSIZE; j++)
88: *(int *)(pte+j) &= PG_PROT;
89: c->c_gone = 1;
90: goto free;
91: }
92: if (c->c_free) {
93: pcnt -= CLSIZE;
94: for (j = 0; j < CLSIZE; j++)
95: *(int *)(pte+j) &= PG_PROT;
96: if (c->c_type == CTEXT)
97: distpte(&text[c->c_ndx], (int)c->c_page, pte);
98: c->c_gone = 1;
99: goto free;
100: }
101: if (size == 0)
102: spte = pte;
103: size += CLSIZE;
104: continue;
105: }
106: if (pte->pg_fod) {
107: for (j = 0; j < CLSIZE; j++)
108: *(int *)(pte+j) &= PG_PROT;
109: }
110: free:
111: if (size) {
112: memfree(spte, size, 1);
113: size = 0;
114: }
115: }
116: if (size)
117: memfree(spte, size, 1);
118: return (pcnt);
119: }
120:
121: /*
122: * Unlink a page frame from the free list -
123: *
124: * Performed if the page being reclaimed
125: * is in the free list.
126: */
127: munlink(pf)
128: unsigned pf;
129: {
130: register int next, prev;
131:
132: next = cmap[pgtocm(pf)].c_next;
133: prev = cmap[pgtocm(pf)].c_prev;
134: cmap[prev].c_next = next;
135: cmap[next].c_prev = prev;
136: cmap[pgtocm(pf)].c_free = 0;
137: if (freemem < minfree)
138: wakeup((caddr_t)&proc[PAGEPID]); /* jolt paging daemon */
139: freemem -= CLSIZE;
140: }
141:
142: /*
143: * Allocate memory -
144: *
145: * The free list appears as a doubly linked list
146: * in the core map with cmap[0] serving as a header.
147: */
148: memall(pte, size, p, type)
149: register struct pte *pte;
150: int size;
151: struct proc *p;
152: {
153: register struct cmap *c;
154: register struct pte *rpte;
155: register struct proc *rp;
156: register int i, j;
157: int px;
158: unsigned pf;
159: struct cmap *c1, *c2;
160:
161: if (size % CLSIZE)
162: panic("memall");
163: if (size > freemem)
164: return (0);
165: px = p - proc;
166: for (i = size; i > 0; i -= CLSIZE) {
167: c = &cmap[cmap[CMHEAD].c_next];
168: if (c->c_free == 0)
169: panic("dup mem alloc");
170: if (c->c_gone == 0 && c->c_type != CSYS) {
171: if (c->c_type == CTEXT)
172: rp = text[c->c_ndx].x_caddr;
173: else
174: rp = &proc[c->c_ndx];
175: switch (c->c_type) {
176:
177: case CTEXT:
178: rpte = tptopte(rp, c->c_page);
179: break;
180:
181: case CDATA:
182: rpte = dptopte(rp, c->c_page);
183: break;
184:
185: case CSTACK:
186: rpte = sptopte(rp, c->c_page);
187: break;
188: }
189: zapcl(rpte, pg_pfnum) = 0;
190: if (c->c_type == CTEXT)
191: distpte(&text[c->c_ndx], (int)c->c_page, rpte);
192: }
193: switch (type) {
194:
195: case CSYS:
196: c->c_ndx = px;
197: break;
198:
199: case CTEXT:
200: c->c_page = vtotp(p, ptetov(p, pte));
201: c->c_ndx = p->p_textp - &text[0];
202: break;
203:
204: case CDATA:
205: c->c_page = vtodp(p, ptetov(p, pte));
206: c->c_ndx = px;
207: break;
208:
209: case CSTACK:
210: c->c_page = vtosp(p, ptetov(p, pte));
211: c->c_ndx = px;
212: break;
213: }
214: if (c->c_blkno) {
215: /*
216: * This is very like munhash(), except
217: * that we really don't want to bother
218: * to calculate a dev to pass to it.
219: */
220: j = CMHASH(c->c_blkno);
221: c1 = &cmap[cmhash[j]];
222: if (c1 == c)
223: cmhash[j] = c1->c_hlink;
224: else {
225: for (;;) {
226: if (c1 == ecmap)
227: panic("memall ecmap");
228: c2 = c1;
229: c1 = &cmap[c2->c_hlink];
230: if (c1 == c)
231: break;
232: }
233: c2->c_hlink = c1->c_hlink;
234: }
235: if (mfind(c->c_mdev, (daddr_t)c->c_blkno))
236: panic("memall mfind");
237: c1->c_mdev = 0;
238: c1->c_blkno = 0;
239: c1->c_hlink = 0;
240: }
241: pf = cmtopg(c - cmap);
242: for (j = 0; j < CLSIZE; j++)
243: *(int *)pte++ = pf++;
244: c->c_free = 0;
245: c->c_gone = 0;
246: if (c->c_intrans || c->c_want)
247: panic("memall intrans|want");
248: c->c_lock = 1;
249: c->c_type = type;
250: freemem -= CLSIZE;
251: j = c->c_next;
252: cmap[CMHEAD].c_next = j;
253: cmap[j].c_prev = CMHEAD;
254: }
255: return (size);
256: }
257:
258: /*
259: * Free memory -
260: *
261: * The page frames being returned are inserted
262: * to the head/tail of the free list depending
263: * on whether there is any possible future use of them.
264: *
265: * If the freemem count had been zero,
266: * the processes sleeping for memory
267: * are awakened.
268: */
269: memfree(pte, size, detach)
270: register struct pte *pte;
271: register int size;
272: {
273: register int i, j, prev, next;
274: register struct cmap *c;
275:
276: if (size % CLSIZE)
277: panic("memfree");
278: if (freemem < CLSIZE * KLMAX)
279: wakeup((caddr_t)&freemem);
280: while (size > 0) {
281: size -= CLSIZE;
282: i = pte->pg_pfnum;
283: if (i < firstfree || i > maxfree)
284: panic("bad mem free");
285: i = pgtocm(i);
286: c = &cmap[i];
287: if (c->c_free)
288: panic("dup mem free");
289: if (detach && c->c_type != CSYS) {
290: for (j = 0; j < CLSIZE; j++)
291: *(int *)(pte+j) &= PG_PROT;
292: c->c_gone = 1;
293: }
294: if (detach && c->c_blkno == 0) {
295: next = cmap[CMHEAD].c_next;
296: cmap[next].c_prev = i;
297: c->c_prev = CMHEAD;
298: c->c_next = next;
299: cmap[CMHEAD].c_next = i;
300: } else {
301: prev = cmap[CMHEAD].c_prev;
302: cmap[prev].c_next = i;
303: c->c_next = CMHEAD;
304: c->c_prev = prev;
305: cmap[CMHEAD].c_prev = i;
306: }
307: c->c_free = 1;
308: freemem += CLSIZE;
309: pte += CLSIZE;
310: }
311: }
312:
313: /*
314: * Enter cmap block c on the hash chains.
315: * It contains file system block bn from device dev.
316: * Dev must either be a mounted file system or the swap device
317: * so we panic if getfsx() cannot find it.
318: */
319: mhash(c, mdev, bn)
320: register struct cmap *c;
321: int mdev;
322: daddr_t bn;
323: {
324: register int i = CMHASH(bn);
325:
326: if (mdev == -1)
327: panic("mhash");
328: c->c_hlink = cmhash[i];
329: cmhash[i] = c - cmap;
330: c->c_blkno = bn;
331: c->c_mdev = mdev;
332: }
333:
334: /*
335: * Pull the clist entry of <dev,bn> off the hash chains.
336: * We have checked before calling (using mfind) that the
337: * entry really needs to be unhashed, so panic if we can't
338: * find it (can't happen).
339: */
340: munhash(mdev, bn)
341: register int mdev;
342: daddr_t bn;
343: {
344: register int i = CMHASH(bn);
345: register struct cmap *c1, *c2;
346:
347: c1 = &cmap[cmhash[i]];
348: if (c1 == ecmap)
349: panic("munhash");
350: if (c1->c_blkno == bn && mdev == c1->c_mdev)
351: cmhash[i] = c1->c_hlink;
352: else {
353: for (;;) {
354: c2 = c1;
355: c1 = &cmap[c2->c_hlink];
356: if (c1 == ecmap)
357: panic("munhash");
358: if (c1->c_blkno == bn && mdev == c1->c_mdev)
359: break;
360: }
361: c2->c_hlink = c1->c_hlink;
362: }
363: if (mfind(mdev, bn))
364: panic("munhash mfind");
365: c1->c_mdev = 0;
366: c1->c_blkno = 0;
367: c1->c_hlink = 0;
368: }
369:
370: /*
371: * Look for block bn of device dev in the free pool.
372: * Currently it should not be possible to find it unless it is
373: * c_free and c_gone, although this may later not be true.
374: * (This is because active texts are locked against file system
375: * writes by the system.)
376: */
377: struct cmap *
378: mfind(mdev, bn)
379: register int mdev;
380: daddr_t bn;
381: {
382: register struct cmap *c1 = &cmap[cmhash[CMHASH(bn)]];
383:
384: while (c1 != ecmap) {
385: if (c1->c_blkno == bn && c1->c_mdev == mdev)
386: return (c1);
387: c1 = &cmap[c1->c_hlink];
388: }
389: return ((struct cmap *)0);
390: }
391:
392: /*
393: * Purge blocks from device dev from incore cache
394: * before umount().
395: */
396: mpurge(mdev)
397: int mdev;
398: {
399: register struct cmap *c1, *c2;
400: register int i;
401:
402: for (i = 0; i < CMHSIZ; i++) {
403: more:
404: c1 = &cmap[cmhash[i]];
405: if (c1 == ecmap)
406: continue;
407: if (c1->c_mdev == mdev)
408: cmhash[i] = c1->c_hlink;
409: else {
410: for (;;) {
411: c2 = c1;
412: c1 = &cmap[c1->c_hlink];
413: if (c1 == ecmap)
414: goto cont;
415: if (c1->c_mdev == mdev)
416: break;
417: }
418: c2->c_hlink = c1->c_hlink;
419: }
420: c1->c_mdev = 0;
421: c1->c_blkno = 0;
422: c1->c_hlink = 0;
423: goto more;
424: cont:
425: ;
426: }
427: }
428:
429: /*
430: * Initialize core map
431: */
432: meminit(first, last)
433: int first, last;
434: {
435: register int i;
436: register struct cmap *c;
437:
438: firstfree = clrnd(first);
439: maxfree = clrnd(last - (CLSIZE - 1));
440: freemem = maxfree - firstfree;
441: ecmx = ecmap - cmap;
442: if (ecmx < freemem / CLSIZE)
443: freemem = ecmx * CLSIZE;
444: for (i = 1; i <= freemem / CLSIZE; i++) {
445: cmap[i-1].c_next = i;
446: c = &cmap[i];
447: c->c_prev = i-1;
448: c->c_free = 1;
449: c->c_gone = 1;
450: c->c_type = CSYS;
451: c->c_mdev = 0;
452: c->c_blkno = 0;
453: }
454: cmap[freemem / CLSIZE].c_next = CMHEAD;
455: for (i = 0; i < CMHSIZ; i++)
456: cmhash[i] = ecmx;
457: cmap[CMHEAD].c_prev = freemem / CLSIZE;
458: cmap[CMHEAD].c_type = CSYS;
459: avefree = freemem;
460: }
461:
462: /*
463: * Wait for frame pf to become unlocked
464: * if it is currently locked.
465: *
466: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
467: */
468: mwait(pf)
469: unsigned pf;
470: {
471:
472: mlock(pf);
473: munlock(pf);
474: }
475:
476: /*
477: * Lock a page frame.
478: *
479: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
480: */
481: mlock(pf)
482: unsigned pf;
483: {
484: register struct cmap *c = &cmap[pgtocm(pf)];
485:
486: while (c->c_lock) {
487: c->c_want = 1;
488: sleep((caddr_t)c, PSWP+1);
489: }
490: c->c_lock = 1;
491: }
492:
493: /*
494: * Unlock a page frame.
495: *
496: * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
497: */
498: munlock(pf)
499: unsigned pf;
500: {
501: register struct cmap *c = &cmap[pgtocm(pf)];
502:
503: if (c->c_lock == 0)
504: panic("dup page unlock");
505: if (c->c_want)
506: wakeup((caddr_t)c);
507: c->c_lock = 0;
508: c->c_want = 0;
509: }
510:
511: /*
512: * Lock a virtual segment.
513: *
514: * For each cluster of pages, if the cluster is not valid,
515: * touch it to fault it in, otherwise just lock page frame.
516: * Called from physio to ensure that the pages
517: * participating in raw i/o are valid and locked.
518: * We use SDLYU to keep pagein from unlocking pages,
519: * so they make it safely back here locked.
520: */
521: vslock(base, count)
522: caddr_t base;
523: {
524: register unsigned v;
525: register int npf;
526: register struct pte *pte;
527:
528: u.u_procp->p_flag |= SDLYU;
529: v = btop(base);
530: pte = vtopte(u.u_procp, v);
531: npf = btoc(count + ((int)base & CLOFSET));
532: while (npf > 0) {
533: if (pte->pg_v)
534: mlock(pte->pg_pfnum);
535: else
536: if (fubyte((caddr_t)ctob(v)) < 0)
537: panic("vslock");
538: pte += CLSIZE;
539: v += CLSIZE;
540: npf -= CLSIZE;
541: }
542: u.u_procp->p_flag &= ~SDLYU;
543: }
544:
545: /*
546: * Unlock a virtual segment.
547: */
548: vsunlock(base, count, rw)
549: caddr_t base;
550: {
551: register struct pte *pte;
552: register int npf;
553:
554: pte = vtopte(u.u_procp, btop(base));
555: npf = btoc(count + ((int)base & CLOFSET));
556: while (npf > 0) {
557: munlock(pte->pg_pfnum);
558: if (rw == B_READ) /* Reading from device writes memory */
559: pte->pg_m = 1;
560: pte += CLSIZE;
561: npf -= CLSIZE;
562: }
563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.