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