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