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