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