|
|
1.1 root 1: /* vmpage.c 4.16 81/05/12 */
2:
3: #include "sys/param.h"
4: #include "sys/systm.h"
5: #include "sys/inode.h"
6: #include "sys/user.h"
7: #include "sys/proc.h"
8: #include "sys/reg.h"
9: #include "sys/pte.h"
10: #include "sys/buf.h"
11: #include "sys/text.h"
12: #include "sys/mtpr.h"
13: #include "sys/cmap.h"
14: #include "sys/vm.h"
15: #include "sys/file.h"
16:
17: struct pte *Pushmap;
18: struct user *pushutl;
19:
20: int nohash = 0;
21: /*
22: * Handle a page fault.
23: *
24: * Basic outline
25: * If page is allocated, but just not valid:
26: * Wait if intransit, else just revalidate
27: * Done
28: * Compute <dev,bn> from which page operation would take place
29: * If page is text page, and filling from file system or swap space:
30: * If in free list cache, reattach it and then done
31: * Allocate memory for page in
32: * If block here, restart because we could have swapped, etc.
33: * Lock process from swapping for duration
34: * Update pte's to reflect that page is intransit.
35: * If page is zero fill on demand:
36: * Clear pages and flush free list cache of stale cacheing
37: * for this swap page (e.g. before initializing again due
38: * to 407/410 exec).
39: * If page is fill from file and in buffer cache:
40: * Copy the page from the buffer cache.
41: * If not a fill on demand:
42: * Determine swap address and cluster to page in
43: * Do the swap to bring the page in
44: * Instrument the pagein
45: * After swap validate the required new page
46: * Leave prepaged pages reclaimable (not valid)
47: * Update shared copies of text page tables
48: * Complete bookkeeping on pages brought in:
49: * No longer intransit
50: * Hash text pages into core hash structure
51: * Unlock pages (modulo raw i/o requirements)
52: * Flush translation buffer
53: * Process pagein is done
54: */
55: int preptofree = 1; /* send pre-paged pages to free list */
56: static struct cmap dbcmap; /* debug */
57:
58: pagein(virtaddr,uu)
59: unsigned virtaddr;
60: register struct user *uu;
61: {
62: register struct proc *p;
63: register struct pte *pte;
64: register struct inode *ip;
65: register unsigned v;
66: unsigned pf;
67: int type, fileno, prot;
68: struct pte opte;
69: struct buf *bp;
70: dev_t dev;
71: register int i;
72: int klsize;
73: unsigned vsave;
74: struct cmap *c;
75: int j;
76: daddr_t bn, bncache, bnswap;
77: int otime, olbolt, oicr, a, s;
78:
79: s = spl6();
80: otime = time, olbolt = lbolt, oicr = mfpr(ICR);
81: cnt.v_faults++;
82: /*
83: * Classify faulted page into a segment and get a pte
84: * for the faulted page.
85: */
86: vsave = v = clbase(btop(virtaddr));
87: p = uu->u_procp;
88: if (isatsv(p, v))
89: type = CTEXT;
90: else if (isassv(p, v))
91: type = CSTACK;
92: else
93: type = CDATA;
94: pte = vtopte(p, v);
95: if (pte->pg_v)
96: panic("pagein");
97:
98: /*
99: * If page is reclaimable, reclaim it.
100: * If page is text and intransit, sleep while it is intransit,
101: * If it is valid after the sleep, we are done.
102: * Otherwise we have to start checking again, since page could
103: * even be reclaimable now (we may have swapped for a long time).
104: */
105: restart:
106: if (pte->pg_fod == 0 && pte->pg_pfnum) {
107: if (type == CTEXT && cmap[pgtocm(pte->pg_pfnum)].c_intrans) {
108: sleep((caddr_t)p->p_textp, PSWP+1);
109: pte = vtopte(p, v);
110: if (pte->pg_v) {
111: valid:
112: if (p->p_flag & SDLYU) {
113: mlock(pte->pg_pfnum);
114: if (!pte->pg_v) {
115: munlock(pte->pg_pfnum);
116: goto restart;
117: }
118: }
119: tbiscl(v);
120: cnt.v_intrans++;
121: return;
122: }
123: goto restart;
124: }
125: /*
126: * If page is in the free list, then take
127: * it back into the resident set, updating
128: * the size recorded for the resident set.
129: */
130: if (cmap[pgtocm(pte->pg_pfnum)].c_free) {
131: munlink(pte->pg_pfnum);
132: cnt.v_pgfrec++;
133: if (type == CTEXT)
134: p->p_textp->x_rssize += CLSIZE;
135: else
136: p->p_rssize += CLSIZE;
137: }
138: pte->pg_v = 1;
139: if (anycl(pte, pg_m))
140: pte->pg_m = 1;
141: distcl(pte);
142: if (type == CTEXT)
143: distpte(p->p_textp, vtotp(p, v), pte);
144: if (p->p_flag & SDLYU) {
145: mlock(pte->pg_pfnum);
146: if (!pte->pg_v) {
147: munlock(pte->pg_pfnum);
148: goto restart;
149: }
150: }
151: uu->u_vm.vm_minflt++;
152: cnt.v_pgrec++;
153: tbiscl(v);
154: a = vmtime(otime, olbolt, oicr);
155: rectime += a;
156: if (a >= 0)
157: vmfltmon(rmon, a, rmonmin, rres, NRMON);
158: splx(s);
159: return;
160: }
161: splx(s);
162: /*
163: * <dev,bn> is where data comes from/goes to.
164: * <dev,bncache> is where data is cached from/to.
165: * <swapdev,bnswap> is where data will eventually go.
166: */
167: if (pte->pg_fod == 0) {
168: fileno = -1;
169: bnswap = bncache = bn = dbtofsb(swapdev,
170: vtod(p, v, &uu->u_dmap, &uu->u_smap));
171: dev = swapdev;
172: } else {
173: fileno = ((struct fpte *)pte)->pg_source + PG_FMIN;
174: bn = ((struct fpte *)pte)->pg_blkno;
175: bnswap = dbtofsb(swapdev, vtod(p, v, &uu->u_dmap, &uu->u_smap));
176: if (fileno > PG_FMAX)
177: panic("pagein pg_source");
178: if (fileno == PG_FTEXT) {
179: if (p->p_textp == 0)
180: panic("pagein PG_FTEXT");
181: dev = p->p_textp->x_iptr->i_dev;
182: bncache = bn;
183: } else if (fileno == PG_FZERO) {
184: dev = swapdev;
185: bncache = bnswap;
186: } else {
187: if (uu->u_ofile[fileno] == NULL)
188: panic("pagein uu->u_ofile");
189: ip = uu->u_ofile[fileno]->f_inode;
190: dev = ip->i_dev;
191: }
192: }
193: klsize = 1;
194: opte = *pte;
195:
196: /*
197: * Check for text detached but in free list.
198: * This can happen only if the page is filling
199: * from a inode or from the swap device, (e.g. not when reading
200: * in 407/410 execs to a zero fill page.)
201: * honour lock bit to avoid race with pageout
202: */
203: if (type == CTEXT && fileno != PG_FZERO && !nohash) {
204: while ((c = mfind(getfsx(dev), bncache)) != 0) {
205: pf = cmtopg(c - cmap);
206: if (c->c_lock == 0)
207: break;
208: mlock(pf);
209: munlock(pf);
210: }
211: if (c) {
212: dbcmap = *c;
213: if (c->c_type != CTEXT || c->c_gone == 0 ||
214: c->c_free == 0)
215: panic("pagein mfind");
216: p->p_textp->x_rssize += CLSIZE;
217: /*
218: * Following code mimics memall().
219: */
220: pf = cmtopg(c - cmap);
221: munlink(pf);
222: for (j = 0; j < CLSIZE; j++) {
223: *(int *)pte = pf++;
224: pte->pg_prot = opte.pg_prot;
225: pte++;
226: }
227: pte -= CLSIZE;
228: c->c_free = 0;
229: c->c_gone = 0;
230: if (c->c_intrans || c->c_want)
231: panic("pagein intrans|want");
232: c->c_lock = 1;
233: if (c->c_page != vtotp(p, v))
234: panic("pagein c_page chgd");
235: c->c_ndx = p->p_textp - &text[0];
236: if (dev == swapdev)
237: cnt.v_xsfrec++;
238: else
239: cnt.v_xifrec++;
240: cnt.v_pgrec++;
241: uu->u_vm.vm_minflt++;
242: if (dev != swapdev) {
243: c = mfind(MSWAPX, bnswap);
244: if (c)
245: munhash(MSWAPX, bnswap);
246: pte->pg_swapm = 1;
247: }
248: goto skipswap;
249: }
250: }
251:
252: /*
253: * Wasn't reclaimable or reattachable.
254: * Have to prepare to bring the page in.
255: * We allocate the page before locking so we will
256: * be swappable if there is no free memory.
257: * If we block we have to start over, since anything
258: * could have happened.
259: */
260: if (freemem < CLSIZE * KLMAX) {
261: while (freemem < CLSIZE * KLMAX)
262: sleep((caddr_t)&freemem, PSWP+2);
263: pte = vtopte(p, v);
264: if (pte->pg_v)
265: goto valid;
266: goto restart;
267: }
268:
269: /*
270: * Now can get memory and committed to bringing in the page.
271: * Lock this process, get a page,
272: * construct the new pte, and increment
273: * the (process or text) resident set size.
274: */
275: p->p_flag |= SPAGE;
276: (void) memall(pte, CLSIZE, p, type);
277: pte->pg_prot = opte.pg_prot;
278: pf = pte->pg_pfnum;
279: cmap[pgtocm(pf)].c_intrans = 1;
280: distcl(pte);
281: if (type == CTEXT) {
282: p->p_textp->x_rssize += CLSIZE;
283: distpte(p->p_textp, vtotp(p, v), pte);
284: } else
285: p->p_rssize += CLSIZE;
286:
287: /*
288: * Two cases: either fill on demand (zero or text)
289: * or from swap space.
290: */
291: if (opte.pg_fod) {
292: pte->pg_swapm = 1;
293: if (fileno == PG_FZERO || fileno == PG_FTEXT) {
294: /*
295: * Flush any previous text page use of this
296: * swap device block.
297: */
298: if (type == CTEXT) {
299: c = mfind(MSWAPX, bnswap);
300: if (c)
301: munhash(MSWAPX, bnswap);
302: }
303: /*
304: * If zero fill, short-circuit hard work
305: * by just clearing pages.
306: */
307: if (fileno == PG_FZERO) {
308: for (i = 0; i < CLSIZE; i++)
309: clearseg(pf+i);
310: if (type != CTEXT)
311: cnt.v_zfod += CLSIZE;
312: goto skipswap;
313: }
314: cnt.v_exfod += CLSIZE;
315: } else
316: /*
317: * Vreading block... whoops
318: */
319: panic("pagein, vrpages ref'd");
320: /*
321: * Check that block is not in file system buffer cache.
322: * The way the cache is handled now, this
323: * happens only once every 2 days.
324: */
325: if (bp = baddr(dev, bn)) {
326: pte->pg_v = 1;
327: prot = *(int *)pte & PG_PROT;
328: pte->pg_prot = 0;
329: *(int *)pte |= PG_UW;
330: distcl(pte);
331: tbiscl(v);
332: /* THIS ASSUMES THAT CLSIZE*NBPG==BSIZE */
333: bcopy(bp->b_un.b_addr, ptob(v), BSIZE(dev));
334: brelse(bp);
335: pte->pg_prot = 0;
336: *(int *)pte |= prot;
337: goto skipswap;
338: }
339: } else {
340: if (opte.pg_pfnum)
341: panic("pagein pfnum");
342: /*
343: * Fill from swap area. Try to find adjacent
344: * pages to bring in also.
345: */
346: v = kluster(p, v, pte, B_READ, &klsize,
347: (type == CTEXT) ? kltxt :
348: ((p->p_flag & SSEQL) ? klseql : klin), bn);
349: /* THIS COULD BE COMPUTED INCREMENTALLY... */
350: bncache = bn = dbtofsb(swapdev, vtod(p, v, &uu->u_dmap, &uu->u_smap));
351: pte->pg_vreadm = opte.pg_vreadm;
352: }
353:
354: distcl(pte);
355: swap(p, fsbtodb(dev, bn), ptob(v), klsize * ctob(CLSIZE),
356: B_READ, B_PGIN, dev, 0);
357:
358: /*
359: * Instrumentation.
360: */
361: uu->u_vm.vm_majflt++;
362: cnt.v_pgin++;
363: cnt.v_pgpgin += klsize * CLSIZE;
364: a = vmtime(otime, olbolt, oicr) / 100;
365: pgintime += a;
366: if (a >= 0)
367: vmfltmon(pmon, a, pmonmin, pres, NPMON);
368:
369: skipswap:
370: /*
371: * Fix page table entries.
372: *
373: * Only page requested in is validated, and rest of pages
374: * can be ``reclaimed''. This allows system to reclaim prepaged pages
375: * quickly if they are not used and memory is tight.
376: */
377: pte = vtopte(p, vsave);
378: pte->pg_v = 1;
379: distcl(pte);
380: if (type == CTEXT) {
381: distpte(p->p_textp, vtotp(p, vsave), pte);
382: if (opte.pg_fod)
383: p->p_textp->x_flag |= XWRIT;
384: wakeup((caddr_t)p->p_textp);
385: }
386:
387: /*
388: * Memall returned page(s) locked. Unlock all
389: * pages in cluster. If locking pages for raw i/o
390: * leave the page which was required to be paged in locked,
391: * but still unlock others.
392: * If text pages, hash into the cmap situation table.
393: */
394: pte = vtopte(p, v);
395: for (i = 0; i < klsize; i++) {
396: c = &cmap[pgtocm(pte->pg_pfnum)];
397: c->c_intrans = 0;
398: if (type == CTEXT && c->c_blkno == 0 && bncache && !nohash) {
399: mhash(c, getfsx(dev), bncache);
400: bncache++;
401: }
402: if (v != vsave || (p->p_flag & SDLYU) == 0)
403: munlock(pte->pg_pfnum);
404: if (v != vsave && type != CTEXT && preptofree) {
405: /*
406: * Throw pre-paged data/stack pages at the
407: * bottom of the free list.
408: */
409: p->p_rssize -= CLSIZE;
410: memfree(pte, CLSIZE, 0);
411: }
412: tbiscl(v); /* conservative ? */
413: v += CLSIZE;
414: pte += CLSIZE;
415: }
416:
417: /*
418: * All done.
419: */
420: p->p_flag &= ~SPAGE;
421: if (p->p_flag & SPROCWT) {
422: register s = spl6();
423: p->p_flag &= ~SPROCWT;
424: p->p_usrpri = 127;
425: wakeup((caddr_t)&(p->p_stat));
426: ++runrun;
427: splx(s);
428: }
429:
430: /*
431: * If process is declared fifo, memory is tight,
432: * and this was a data page-in, free memory
433: * klsdist pagein clusters away from the current fault.
434: */
435: if ((p->p_flag&SSEQL) && freemem < lotsfree &&
436: type == CDATA && p == u.u_procp) {
437: int k = (vtodp(p, vsave) / CLSIZE) / klseql;
438: #ifdef notdef
439: if (vsave > uu->u_vsave)
440: k -= klsdist;
441: else
442: k += klsdist;
443: dpageout(p, k * klseql * CLSIZE, klout*CLSIZE);
444: uu->u_vsave = vsave;
445: #else
446: dpageout(p, (k - klsdist) * klseql * CLSIZE, klout*CLSIZE);
447: dpageout(p, (k + klsdist) * klseql * CLSIZE, klout*CLSIZE);
448: #endif
449: }
450: }
451:
452: #if defined(BERT)
453: int dmod = 1000000;
454: int dcnt;
455: #endif
456: /*
457: * Take away n pages of data space
458: * starting at data page dp.
459: * Used to take pages away from sequential processes.
460: * Mimics pieces of code in pageout() below.
461: */
462: dpageout(p, dp, n)
463: struct proc *p;
464: int dp, n;
465: {
466: register struct cmap *c;
467: int i, klsize;
468: register struct pte *pte;
469: unsigned v;
470: daddr_t daddr;
471:
472: if (dp < 0) {
473: n += dp;
474: dp = 0;
475: }
476: if (dp + n > p->p_dsize)
477: n = p->p_dsize - dp;
478: #if defined(BERT)
479: if (++dcnt % dmod == 0)
480: printf("dp %d, n %d\n", dp, n);
481: #endif
482: for (i = 0; i < n; i += CLSIZE, dp += CLSIZE) {
483: pte = dptopte(p, dp);
484: if (pte->pg_fod || pte->pg_pfnum == 0)
485: continue;
486: c = &cmap[pgtocm(pte->pg_pfnum)];
487: if (c->c_lock || c->c_free)
488: continue;
489: if (pte->pg_v) {
490: pte->pg_v = 0;
491: if (anycl(pte, pg_m))
492: pte->pg_m = 1;
493: distcl(pte);
494: }
495: if (dirtycl(pte)) {
496: if (bswlist.av_forw == NULL)
497: continue;
498: mlock(pte->pg_pfnum);
499: if (anycl(pte, pg_m)) {
500: pte->pg_vreadm = 1;
501: pte->pg_m = 0;
502: }
503: pte->pg_swapm = 0;
504: distcl(pte);
505: p->p_poip++;
506: v = kluster(p, dptov(p, dp), pte, B_WRITE,
507: &klsize, klout, (daddr_t)0);
508: /* THIS ASSUMES THAT p == u.u_procp */
509: daddr = vtod(p, v, &u.u_dmap, &u.u_smap);
510: swap(p, daddr, ptob(v), klsize * ctob(CLSIZE),
511: B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
512: } else {
513: if (c->c_gone == 0)
514: p->p_rssize -= CLSIZE;
515: memfree(pte, CLSIZE, 0);
516: cnt.v_seqfree += CLSIZE;
517: }
518: }
519: }
520:
521: int fifo = 0;
522: /*
523: * The page out daemon, which runs as process 2.
524: *
525: * As long as there are at least lotsfree pages,
526: * this process is not run. When the number of free
527: * pages stays in the range desfree to lotsfree,
528: * this daemon runs through the pages in the loop
529: * at a rate determined in vmsched(), simulating the missing
530: * hardware reference bit, and cleaning pages and transferring
531: * them to the free list.
532: */
533: int hand;
534: pageout()
535: {
536: register struct proc *rp;
537: register struct text *xp;
538: register struct cmap *c;
539: register struct pte *pte;
540: int count, pushes;
541: swblk_t daddr;
542: unsigned v;
543: int maxhand = pgtocm(maxfree);
544: int klsize;
545:
546: loop:
547: /*
548: * Before sleeping, look to see if there are any swap I/O headers
549: * in the ``cleaned'' list that correspond to dirty
550: * pages that have been pushed asynchronously. If so,
551: * empty the list by calling cleanup().
552: *
553: * N.B.: We guarantee never to block while the cleaned list is nonempty.
554: */
555: (void) spl6();
556: if (bclnlist != NULL)
557: cleanup();
558: sleep((caddr_t)&proc[2], PSWP+1);
559: (void) spl0();
560: count = 0;
561: pushes = 0;
562: while (nscan < desscan && freemem < lotsfree) {
563: top:
564: /*
565: * An iteration of the clock pointer (hand) around the loop.
566: * Look at the page at hand. If it is a
567: * locked (for physical i/o e.g.), system (u., page table)
568: * or free, then leave it alone.
569: * Otherwise, find a process and text pointer for the
570: * page, and a virtual page number in either the
571: * process or the text image.
572: */
573: c = &cmap[hand];
574: if (c->c_lock || c->c_free)
575: goto skip;
576: switch (c->c_type) {
577:
578: case CSYS:
579: goto skip;
580:
581: case CTEXT:
582: xp = &text[c->c_ndx];
583: rp = xp->x_caddr;
584: v = tptov(rp, c->c_page);
585: pte = tptopte(rp, c->c_page);
586: break;
587:
588: case CDATA:
589: case CSTACK:
590: rp = &proc[c->c_ndx];
591: while (rp->p_flag & SNOVM)
592: rp = rp->p_xlink;
593: xp = rp->p_textp;
594: if (c->c_type == CDATA) {
595: v = dptov(rp, c->c_page);
596: pte = dptopte(rp, c->c_page);
597: } else {
598: v = sptov(rp, c->c_page);
599: pte = sptopte(rp, c->c_page);
600: }
601: break;
602: }
603: if (pte->pg_pfnum != cmtopg(hand))
604: panic("bad c_page");
605: /*
606: * If page is valid; make invalid but reclaimable.
607: * If this pte is not valid, then it must be reclaimable
608: * and we can add it to the free list.
609: */
610: if (pte->pg_v) {
611: pte->pg_v = 0;
612: if (anycl(pte, pg_m))
613: pte->pg_m = 1;
614: distcl(pte);
615: if (c->c_type == CTEXT)
616: distpte(xp, vtotp(rp, v), pte);
617: if ((rp->p_flag & (SSEQL|SUANOM)) || fifo ||
618: rp->p_rssize > rp->p_maxrss)
619: goto take;
620: } else {
621: take:
622: if (c->c_type != CTEXT) {
623: /*
624: * Guarantee a minimal investment in data
625: * space for jobs in balance set.
626: */
627: if (rp->p_rssize < saferss - rp->p_slptime)
628: goto skip;
629: }
630:
631: /*
632: * If the page is currently dirty, we
633: * have to arrange to have it cleaned before it
634: * can be freed. We mark it clean immediately.
635: * If it is reclaimed while being pushed, then modified
636: * again, we are assured of the correct order of
637: * writes because we lock the page during the write.
638: * This guarantees that a swap() of this process (and
639: * thus this page), initiated in parallel, will,
640: * in fact, push the page after us.
641: *
642: * The most general worst case here would be for
643: * a reclaim, a modify and a swapout to occur
644: * all before the single page transfer completes.
645: */
646: if (dirtycl(pte)) {
647: /*
648: * Limit pushes to avoid saturating
649: * pageout device.
650: *
651: * MAGIC 4 BECAUSE WE RUN EVERY 1/4 SEC (clock)
652: */
653: if (pushes > maxpgio / 4)
654: goto skip;
655: pushes++;
656: /*
657: * If the process is being swapped out
658: * or about to exit, do not bother with its
659: * dirty pages
660: */
661: if (rp->p_flag & (SLOCK|SWEXIT))
662: goto skip;
663:
664: /*
665: * Now carefully make sure that there will
666: * be a header available for the push so that
667: * we will not block waiting for a header in
668: * swap(). The reason this is important is
669: * that we (proc[2]) are the one who cleans
670: * dirty swap headers and we could otherwise
671: * deadlock waiting for ourselves to clean
672: * swap headers. The sleep here on &proc[2]
673: * is actually (effectively) a sleep on both
674: * ourselves and &bswlist, and this is known
675: * to iodone and swap in bio.c. That is,
676: * &proc[2] will be awakened both when dirty
677: * headers show up and also to get the pageout
678: * daemon moving.
679: */
680: (void) spl6();
681: if (bclnlist != NULL)
682: cleanup();
683: if (bswlist.av_forw == NULL) {
684: bswlist.b_flags |= B_WANTED;
685: sleep((caddr_t)&proc[2], PSWP+2);
686: (void) spl0();
687: /*
688: * Page disposition may have changed
689: * since process may have exec'ed,
690: * forked, exited or just about
691: * anything else... try this page
692: * frame again, from the top.
693: */
694: goto top;
695: }
696: (void) spl0();
697:
698: mlock((unsigned)cmtopg(hand));
699: uaccess(rp, Pushmap, pushutl);
700: /*
701: * Now committed to pushing the page...
702: */
703: if (anycl(pte, pg_m)) {
704: pte->pg_vreadm = 1;
705: pte->pg_m = 0;
706: }
707: pte->pg_swapm = 0;
708: distcl(pte);
709: if (c->c_type == CTEXT) {
710: xp->x_poip++;
711: distpte(xp, vtotp(rp, v), pte);
712: } else
713: rp->p_poip++;
714: v = kluster(rp, v, pte, B_WRITE, &klsize, klout, (daddr_t)0);
715: if (klsize == 0)
716: panic("pageout klsize");
717: daddr = vtod(rp, v, &pushutl->u_dmap, &pushutl->u_smap);
718: swap(rp, daddr, ptob(v), klsize * ctob(CLSIZE),
719: B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
720: /*
721: * The cleaning of this page will be
722: * completed later, in cleanup() called
723: * (synchronously) by us (proc[2]). In
724: * the meantime, the page frame is locked
725: * so no havoc can result.
726: */
727: goto skip;
728:
729: }
730: /*
731: * Decrement the resident set size of the current
732: * text object/process, and put the page in the
733: * free list. Note that we don't give memfree the
734: * pte as its argument, since we don't want to destroy
735: * the pte. If it hasn't already been discarded
736: * it may yet have a chance to be reclaimed from
737: * the free list.
738: */
739: if (c->c_gone == 0)
740: if (c->c_type == CTEXT)
741: xp->x_rssize -= CLSIZE;
742: else
743: rp->p_rssize -= CLSIZE;
744: memfree(pte, CLSIZE, 0);
745: cnt.v_dfree += CLSIZE;
746:
747: /*
748: * We managed to add a page to the free list,
749: * so we give ourselves another couple of trips
750: * around the loop.
751: */
752: count = 0;
753: }
754: skip:
755: cnt.v_scan++;
756: nscan++;
757: if (++hand >= maxhand) {
758: hand = 0;
759: cnt.v_rev++;
760: if (count > 2) {
761: /*
762: * Extremely unlikely, but we went around
763: * the loop twice and didn't get anywhere.
764: * Don't cycle, stop till the next clock tick.
765: */
766: goto loop;
767: }
768: count++;
769: }
770: }
771: goto loop;
772: }
773:
774: /*
775: * Process the ``cleaned'' list.
776: *
777: * Scan through the linked list of swap I/O headers
778: * and free the corresponding pages that have been
779: * cleaned by being written back to the paging area.
780: * If the page has been reclaimed during this time,
781: * we do not free the page. As they are processed,
782: * the swap I/O headers are removed from the cleaned
783: * list and inserted into the free list.
784: */
785: cleanup()
786: {
787: register struct buf *bp;
788: register struct proc *rp;
789: register struct text *xp;
790: register struct cmap *c;
791: register struct pte *pte;
792: unsigned pf;
793: register int i;
794: int s;
795:
796: for (;;) {
797: s = spl6();
798: if ((bp = bclnlist) == NULL) {
799: splx(s);
800: break;
801: }
802: bclnlist = bp->av_forw;
803: splx(s);
804: pte = dptopte(&proc[2], btop(bp->b_un.b_addr));
805: for (i = 0; i < bp->b_bcount; i += CLSIZE * NBPG) {
806: pf = pte->pg_pfnum;
807: munlock(pf);
808: c = &cmap[pgtocm(pf)];
809: if (c->c_gone) {
810: memfree(pte, CLSIZE, 0);
811: cnt.v_dfree += CLSIZE;
812: }
813: pte += CLSIZE;
814: }
815: c = &cmap[pgtocm(bp->b_pfcent)];
816: switch (c->c_type) {
817:
818: case CSYS:
819: panic("cleanup CSYS");
820:
821: case CTEXT:
822: xp = &text[c->c_ndx];
823: xp->x_poip--;
824: if (xp->x_poip == 0)
825: wakeup((caddr_t)&xp->x_poip);
826: break;
827:
828: case CDATA:
829: case CSTACK:
830: rp = &proc[c->c_ndx];
831: while (rp->p_flag & SNOVM)
832: rp = rp->p_xlink;
833: rp->p_poip--;
834: if (rp->p_poip == 0)
835: wakeup((caddr_t)&rp->p_poip);
836: break;
837: }
838: if (c->c_gone == 0) {
839: switch (c->c_type) {
840:
841: case CTEXT:
842: pte = tptopte(xp->x_caddr, c->c_page);
843: break;
844:
845: case CDATA:
846: pte = dptopte(rp, c->c_page);
847: break;
848:
849: case CSTACK:
850: pte = sptopte(rp, c->c_page);
851: break;
852: }
853: if (pte->pg_v == 0) {
854: if (c->c_type == CTEXT)
855: xp->x_rssize -= CLSIZE;
856: else
857: rp->p_rssize -= CLSIZE;
858: memfree(pte, CLSIZE, 0);
859: cnt.v_dfree += CLSIZE;
860: }
861: }
862: bp->b_flags = 0;
863: bp->av_forw = bswlist.av_forw;
864: bswlist.av_forw = bp;
865: if (bswlist.b_flags & B_WANTED) {
866: bswlist.b_flags &= ~B_WANTED;
867: wakeup((caddr_t)&bswlist);
868: }
869: }
870: }
871:
872: /*
873: * Kluster locates pages adjacent to the argument pages
874: * that are immediately available to include in the pagein/pageout,
875: * and given the availability of memory includes them.
876: * It knows that the process image is contiguous in chunks;
877: * an assumption here is that CLSIZE * KLMAX is a divisor of dmmin,
878: * so that by looking at KLMAX chunks of pages, all such will
879: * necessarily be mapped swap contiguous.
880: */
881: int noklust;
882: int klicnt[KLMAX];
883: int klocnt[KLMAX];
884:
885: kluster(p, v, pte0, rw, pkl, klsize, bn0)
886: register struct proc *p;
887: unsigned v;
888: struct pte *pte0;
889: int rw, *pkl, klsize;
890: daddr_t bn0;
891: {
892: int type, cl, clmax;
893: int kloff, k, klmax;
894: register struct pte *pte;
895: int klback, klforw;
896: register int i;
897: unsigned v0;
898: daddr_t bn;
899:
900: if (rw == B_READ)
901: klicnt[0]++;
902: else
903: klocnt[0]++;
904: *pkl = 1;
905: if (noklust || klsize <= 1 || klsize > KLMAX || (klsize & (klsize - 1)))
906: return (v);
907: if (rw == B_READ && freemem < CLSIZE * KLMAX)
908: return (v);
909: if (isassv(p, v)) {
910: type = CSTACK;
911: cl = vtosp(p, v) / CLSIZE;
912: clmax = p->p_ssize / CLSIZE;
913: } else if (isadsv(p, v)) {
914: type = CDATA;
915: cl = vtodp(p, v) / CLSIZE;
916: clmax = p->p_dsize / CLSIZE;
917: } else {
918: type = CTEXT;
919: cl = vtotp(p, v) / CLSIZE;
920: clmax = p->p_textp->x_size / CLSIZE;
921: }
922: kloff = cl & (klsize - 1);
923: pte = pte0;
924: bn = bn0;
925: for (k = kloff; --k >= 0;) {
926: if (type == CSTACK)
927: pte += CLSIZE;
928: else
929: pte -= CLSIZE;
930: if (type == CTEXT && rw == B_READ && bn) {
931: bn--;
932: if (mfind(MSWAPX, bn))
933: break;
934: }
935: if (!klok(pte, rw))
936: break;
937: }
938: klback = (kloff - k) - 1;
939: pte = pte0;
940: if ((cl - kloff) + klsize > clmax)
941: klmax = clmax - (cl - kloff);
942: else
943: klmax = klsize;
944: bn = bn0;
945: for (k = kloff; ++k < klmax;) {
946: if (type == CSTACK)
947: pte -= CLSIZE;
948: else
949: pte += CLSIZE;
950: if (type == CTEXT && rw == B_READ && bn) {
951: bn++;
952: if (mfind(MSWAPX, bn))
953: break;
954: }
955: if (!klok(pte, rw))
956: break;
957: }
958: klforw = (k - kloff) - 1;
959: if (klforw + klback == 0)
960: return (v);
961: pte = pte0;
962: if (type == CSTACK) {
963: pte -= klforw * CLSIZE;
964: v -= klforw * CLSIZE;
965: } else {
966: pte -= klback * CLSIZE;
967: v -= klback * CLSIZE;
968: }
969: *pkl = klforw + klback + 1;
970: if (rw == B_READ)
971: klicnt[0]--, klicnt[*pkl - 1]++;
972: else
973: klocnt[0]--, klocnt[*pkl - 1]++;
974: v0 = v;
975: for (i = 0; i < *pkl; i++) {
976: if (pte == pte0)
977: goto cont;
978: if (rw == B_WRITE) {
979: mlock(pte->pg_pfnum);
980: if (anycl(pte, pg_m)) {
981: pte->pg_vreadm = 1;
982: pte->pg_m = 0;
983: }
984: pte->pg_swapm = 0;
985: distcl(pte);
986: if (type == CTEXT)
987: distpte(p->p_textp, vtotp(p, v), pte);
988: } else {
989: struct pte opte;
990: int pf;
991:
992: opte = *pte;
993: if (memall(pte, CLSIZE, p, type) == 0)
994: panic("kluster");
995: pte->pg_prot = opte.pg_prot;
996: pf = pte->pg_pfnum;
997: cmap[pgtocm(pf)].c_intrans = 1;
998: distcl(pte);
999: if (type == CTEXT) {
1000: p->p_textp->x_rssize += CLSIZE;
1001: distpte(p->p_textp, vtotp(p, v), pte);
1002: } else
1003: p->p_rssize += CLSIZE;
1004: /* if (opte.pg_fod == 0) */
1005: pte->pg_vreadm = opte.pg_vreadm;
1006: distcl(pte);
1007: }
1008: cont:
1009: pte += CLSIZE;
1010: v += CLSIZE;
1011: }
1012: return (v0);
1013: }
1014:
1015: klok(pte, rw)
1016: register struct pte *pte;
1017: int rw;
1018: {
1019: register struct cmap *c;
1020:
1021: if (rw == B_WRITE) {
1022: if (pte->pg_fod)
1023: return (0);
1024: if (pte->pg_pfnum == 0)
1025: return (0);
1026: c = &cmap[pgtocm(pte->pg_pfnum)];
1027: if (c->c_lock || c->c_intrans)
1028: return (0);
1029: if (!dirtycl(pte))
1030: return (0);
1031: return (1);
1032: } else {
1033: if (pte->pg_fod)
1034: return (0);
1035: if (pte->pg_pfnum)
1036: return (0);
1037: return (1);
1038: }
1039: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.