Annotation of 43BSDReno/sys/kern/vm_page.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)vm_page.c   7.14 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "user.h"
                     26: #include "proc.h"
                     27: #include "buf.h"
                     28: #include "text.h"
                     29: #include "vnode.h"
                     30: #include "cmap.h"
                     31: #include "vm.h"
                     32: #include "trace.h"
                     33: #include "file.h"
                     34: 
                     35: #include "machine/cpu.h"
                     36: #include "machine/pte.h"
                     37: #include "machine/mtpr.h"
                     38: 
                     39: #if defined(tahoe)
                     40: #if CLSIZE == 1
                     41: #define uncachecl(pte) uncache(pte)
                     42: #endif
                     43: #if CLSIZE == 2
                     44: #define uncachecl(pte) uncache(pte), uncache((pte)+1)
                     45: #endif
                     46: #if CLSIZE > 2
                     47: #define uncachecl(pte) { \
                     48:        register ii; \
                     49:        for (ii = 0; ii < CLSIZE; ii++) \
                     50:                uncache((pte) + ii); \
                     51: }
                     52: #endif
                     53: #else /* tahoe */
                     54: #define uncache(pte)   /* nothing */
                     55: #define uncachecl(pte) /* nothing */
                     56: #endif
                     57: 
                     58: int    nohash = 0;
                     59: /*
                     60:  * Handle a page fault.
                     61:  *
                     62:  * Basic outline
                     63:  *     If page is allocated, but just not valid:
                     64:  *             Wait if intransit, else just revalidate
                     65:  *             Done
                     66:  *     Compute <vp,bn> from which page operation would take place
                     67:  *     If page is text page, and filling from file system or swap space:
                     68:  *             If in free list cache, reattach it and then done
                     69:  *     Allocate memory for page in
                     70:  *             If block here, restart because we could have swapped, etc.
                     71:  *     Lock process from swapping for duration
                     72:  *     Update pte's to reflect that page is intransit.
                     73:  *     If page is zero fill on demand:
                     74:  *             Clear pages and flush free list cache of stale cacheing
                     75:  *             for this swap page (e.g. before initializing again due
                     76:  *             to 407/410 exec).
                     77:  *     If page is fill from file and in buffer cache:
                     78:  *             Copy the page from the buffer cache.
                     79:  *     If not a fill on demand:
                     80:  *             Determine swap address and cluster to page in
                     81:  *     Do the swap to bring the page in
                     82:  *     Instrument the pagein
                     83:  *     After swap validate the required new page
                     84:  *     Leave prepaged pages reclaimable (not valid)
                     85:  *     Update shared copies of text page tables
                     86:  *     Complete bookkeeping on pages brought in:
                     87:  *             No longer intransit
                     88:  *             Hash text pages into core hash structure
                     89:  *             Unlock pages (modulo raw i/o requirements)
                     90:  *             Flush translation buffer
                     91:  *     Process pagein is done
                     92:  */
                     93: #ifdef TRACE
                     94: #define        pgtrace(e)      trace(e,v,u.u_procp->p_pid)
                     95: #else
                     96: #define        pgtrace(e)
                     97: #endif
                     98: 
                     99: int    preptofree = 1;         /* send pre-paged pages to free list */
                    100: 
                    101: pagein(virtaddr, dlyu)
                    102:        unsigned virtaddr;
                    103:        int dlyu;
                    104: {
                    105:        register struct proc *p;
                    106:        register struct pte *pte;
                    107:        register unsigned v;
                    108:        unsigned pf;
                    109:        int type, fileno;
                    110:        struct pte opte;
                    111:        struct vnode *vp;
                    112:        register int i;
                    113:        int klsize;
                    114:        unsigned vsave;
                    115:        struct cmap *c;
                    116:        int j;
                    117:        daddr_t bn, bncache, bnswap;
                    118:        int si, sk;
                    119:        int swerror = 0;
                    120: #ifdef PGINPROF
                    121:        int otime, olbolt, oicr, s;
                    122:        long a;
                    123: 
                    124:        s = splclock();
                    125:        otime = time, olbolt = lbolt, oicr = mfpr(ICR);
                    126: #endif
                    127:        cnt.v_faults++;
                    128:        /*
                    129:         * Classify faulted page into a segment and get a pte
                    130:         * for the faulted page.
                    131:         */
                    132:        vsave = v = clbase(btop(virtaddr));
                    133:        p = u.u_procp;
                    134:        if (isatsv(p, v))
                    135:                type = CTEXT;
                    136:        else if (isassv(p, v))
                    137:                type = CSTACK;
                    138:        else
                    139:                type = CDATA;
                    140:        pte = vtopte(p, v);
                    141:        if (pte->pg_v) {
                    142: #ifdef MAPMEM
                    143:                /* will this ever happen? */
                    144:                if (pte->pg_fod) {
                    145: #ifdef PGINPROF
                    146:                        splx(s);
                    147: #endif
                    148:                        return;
                    149:                }
                    150: #endif
                    151:                panic("pagein");
                    152:        }
                    153: 
                    154:        /*
                    155:         * If page is reclaimable, reclaim it.
                    156:         * If page is text and intransit, sleep while it is intransit,
                    157:         * If it is valid after the sleep, we are done.
                    158:         * Otherwise we have to start checking again, since page could
                    159:         * even be reclaimable now (we may have swapped for a long time).
                    160:         */
                    161: restart:
                    162:        if (pte->pg_fod == 0 && pte->pg_pfnum) {
                    163:                if (type == CTEXT && cmap[pgtocm(pte->pg_pfnum)].c_intrans) {
                    164:                        pgtrace(TR_INTRANS);
                    165:                        sleep((caddr_t)p->p_textp, PSWP+1);
                    166:                        pgtrace(TR_EINTRANS);
                    167:                        pte = vtopte(p, v);
                    168:                        if (pte->pg_v) {
                    169: valid:
                    170:                                if (dlyu) {
                    171:                                        c = &cmap[pgtocm(pte->pg_pfnum)];
                    172:                                        if (c->c_lock) {
                    173:                                                c->c_want = 1;
                    174:                                                sleep((caddr_t)c, PSWP+1);
                    175:                                                goto restart;
                    176:                                        }
                    177:                                        c->c_lock = 1;
                    178:                                }
                    179:                                newptes(pte, v, CLSIZE);
                    180:                                cnt.v_intrans++;
                    181: #ifdef PGINPROF
                    182:                                splx(s);
                    183: #endif
                    184:                                return;
                    185:                        }
                    186:                        goto restart;
                    187:                }
                    188:                /*
                    189:                 * If page is in the free list, then take
                    190:                 * it back into the resident set, updating
                    191:                 * the size recorded for the resident set.
                    192:                 */
                    193:                si = splimp();
                    194:                c = &cmap[pgtocm(pte->pg_pfnum)];
                    195:                if (c->c_free) {
                    196:                        pgtrace(TR_FRECLAIM);
                    197:                        munlink(c);
                    198:                        cnt.v_pgfrec++;
                    199:                        if (type == CTEXT)
                    200:                                p->p_textp->x_rssize += CLSIZE;
                    201:                        else
                    202:                                p->p_rssize += CLSIZE;
                    203:                } else
                    204:                        pgtrace(TR_RECLAIM);
                    205:                splx(si);
                    206:                uncachecl(pte);
                    207:                pte->pg_v = 1;
                    208:                if (anycl(pte, pg_m))
                    209:                        pte->pg_m = 1;
                    210:                distcl(pte);
                    211:                if (type == CTEXT)
                    212:                        distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                    213:                u.u_ru.ru_minflt++;
                    214:                cnt.v_pgrec++;
                    215:                if (dlyu) {
                    216:                        c = &cmap[pgtocm(pte->pg_pfnum)];
                    217:                        if (c->c_lock) {
                    218:                                c->c_want = 1;
                    219:                                sleep((caddr_t)c, PSWP+1);
                    220:                                goto restart;
                    221:                        }
                    222:                        c->c_lock = 1;
                    223:                }
                    224:                newptes(pte, v, CLSIZE);
                    225: #ifdef PGINPROF
                    226:                a = vmtime(otime, olbolt, oicr);
                    227:                rectime += a;
                    228:                if (a >= 0)
                    229:                        vmfltmon(rmon, a, rmonmin, rres, NRMON);
                    230:                splx(s);
                    231: #endif
                    232:                return;
                    233:        }
                    234: #ifdef PGINPROF
                    235:        splx(s);
                    236: #endif
                    237:        /*
                    238:         * <vp,bn> is where data comes from/goes to.
                    239:         * <vp,bncache> is where data is cached from/to.
                    240:         * <swapdev_vp,bnswap> is where data will eventually go.
                    241:         */
                    242:        if (pte->pg_fod == 0) {
                    243:                fileno = -1;
                    244:                bnswap = bncache = bn = vtod(p, v, &u.u_dmap, &u.u_smap);
                    245:                vp = swapdev_vp;
                    246:        } else {
                    247:                fileno = ((struct fpte *)pte)->pg_fileno;
                    248:                bn = ((struct fpte *)pte)->pg_blkno;
                    249:                bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                    250:                if (fileno == PG_FTEXT) {
                    251:                        if (p->p_textp == 0)
                    252:                                panic("pagein PG_FTEXT");
                    253:                        if (VOP_BMAP(p->p_textp->x_vptr, (daddr_t)0, &vp,
                    254:                            (daddr_t *)0)) {
                    255:                                swkill(p, "pagein: filesystem unmounted");
                    256:                                return;
                    257:                        }
                    258:                        bncache = bn;
                    259:                } else if (fileno == PG_FZERO) {
                    260:                        vp = swapdev_vp;
                    261:                        bncache = bnswap;
                    262:                }
                    263:        }
                    264:        klsize = 1;
                    265:        opte = *pte;
                    266: 
                    267:        /*
                    268:         * Check for text detached but in free list.
                    269:         * This can happen only if the page is filling
                    270:         * from a inode or from the swap device, (e.g. not when reading
                    271:         * in 407/410 execs to a zero fill page.)
                    272:         * Honor lock bit to avoid races with pageouts.
                    273:         */
                    274:        if (type == CTEXT && fileno != PG_FZERO && !nohash) {
                    275:                si = splimp();
                    276:                while ((c = mfind(vp, bncache)) != 0) {
                    277:                        if (c->c_lock == 0)
                    278:                                break;
                    279:                        MLOCK(c);
                    280:                        MUNLOCK(c);
                    281:                }
                    282:                if (c) {
                    283:                        if (c->c_type != CTEXT || c->c_gone == 0 ||
                    284:                            c->c_free == 0)
                    285:                                panic("pagein mfind");
                    286:                        p->p_textp->x_rssize += CLSIZE;
                    287:                        /*
                    288:                         * Following code mimics memall().
                    289:                         */
                    290:                        munlink(c);
                    291:                        pf = cmtopg(c - cmap);
                    292:                        for (j = 0; j < CLSIZE; j++) {
                    293:                                *(int *)pte = 0;
                    294:                                pte->pg_pfnum = pf++;
                    295:                                pte->pg_prot = opte.pg_prot;
                    296:                                pte++;
                    297:                        }
                    298:                        pte -= CLSIZE;
                    299:                        c->c_free = 0;
                    300:                        c->c_gone = 0;
                    301:                        if (c->c_intrans || c->c_want)
                    302:                                panic("pagein intrans|want");
                    303:                        c->c_lock = 1;
                    304:                        if (c->c_page != vtotp(p, v))
                    305:                                panic("pagein c_page chgd");
                    306:                        c->c_ndx = p->p_textp - &text[0];
                    307:                        if (vp == swapdev_vp) {
                    308:                                cnt.v_xsfrec++;
                    309:                                pgtrace(TR_XSFREC);
                    310:                        } else {
                    311:                                cnt.v_xifrec++;
                    312:                                pgtrace(TR_XIFREC);
                    313:                        }
                    314:                        cnt.v_pgrec++;
                    315:                        u.u_ru.ru_minflt++;
                    316:                        if (vp != swapdev_vp) {
                    317:                                munhash(swapdev_vp, bnswap);
                    318:                                pte->pg_m = 1;
                    319:                        }
                    320:                        splx(si);
                    321:                        goto skipswap;
                    322:                }
                    323:                splx(si);
                    324:        }
                    325: 
                    326:        /*
                    327:         * Wasn't reclaimable or reattachable.
                    328:         * Have to prepare to bring the page in.
                    329:         * We allocate the page before locking so we will
                    330:         * be swappable if there is no free memory.
                    331:         * If we block we have to start over, since anything
                    332:         * could have happened.
                    333:         */
                    334:        sk = splimp();          /* lock memalls from here into kluster */
                    335:        if (freemem < CLSIZE * KLMAX) {
                    336:                pgtrace(TR_WAITMEM);
                    337:                while (freemem < CLSIZE * KLMAX)
                    338:                        sleep((caddr_t)&freemem, PSWP+2);
                    339:                pgtrace(TR_EWAITMEM);
                    340:                splx(sk);
                    341:                pte = vtopte(p, v);
                    342: #ifdef PGINPROF
                    343:                s = splclock();
                    344: #endif
                    345:                if (pte->pg_v)
                    346:                        goto valid;
                    347:                goto restart;
                    348:        }
                    349: 
                    350:        /*
                    351:         * Now can get memory and committed to bringing in the page.
                    352:         * Lock this process, get a page,
                    353:         * construct the new pte, and increment
                    354:         * the (process or text) resident set size.
                    355:         */
                    356:        p->p_flag |= SPAGE;
                    357:        if (memall(pte, CLSIZE, p, type) == 0)
                    358:                panic("pagein memall");
                    359:        pte->pg_prot = opte.pg_prot;
                    360:        pf = pte->pg_pfnum;
                    361:        cmap[pgtocm(pf)].c_intrans = 1;
                    362:        distcl(pte);
                    363:        if (type == CTEXT) {
                    364:                p->p_textp->x_rssize += CLSIZE;
                    365:                distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                    366:        } else
                    367:                p->p_rssize += CLSIZE;
                    368: 
                    369:        /*
                    370:         * Two cases: either fill on demand (zero, or from file or text)
                    371:         * or from swap space.
                    372:         */
                    373:        if (opte.pg_fod) {
                    374:                pte->pg_m = 1;
                    375:                if (fileno == PG_FZERO || fileno == PG_FTEXT) {
                    376:                        /*
                    377:                         * Flush any previous text page use of this
                    378:                         * swap device block.
                    379:                         */
                    380:                        if (type == CTEXT)
                    381:                                munhash(swapdev_vp, bnswap);
                    382:                        /*
                    383:                         * If zero fill, short-circuit hard work
                    384:                         * by just clearing pages.
                    385:                         */
                    386:                        if (fileno == PG_FZERO) {
                    387:                                pgtrace(TR_ZFOD);
                    388:                                for (i = 0; i < CLSIZE; i++) {
                    389:                                        clearseg(pf+i);
                    390: #if defined(tahoe)
                    391:                                        mtpr(P1DC, (int)virtaddr + i * NBPG);
                    392: #endif
                    393:                                }
                    394:                                if (type != CTEXT)
                    395:                                        cnt.v_zfod += CLSIZE;
                    396:                                splx(sk);
                    397:                                goto skipswap;
                    398:                        }
                    399:                        pgtrace(TR_EXFOD);
                    400:                        cnt.v_exfod += CLSIZE;
                    401:                }
                    402:                /*
                    403:                 * Fill from inode.  Try to find adjacent
                    404:                 * pages to bring in also.
                    405:                 */
                    406:                v = fodkluster(p, v, pte, &klsize, vp, &bn);
                    407:                bncache = bn;
                    408:                splx(sk);
                    409: #ifdef TRACE
                    410:                if (type != CTEXT)
                    411:                        trace(TR_XFODMISS, vp, bn);
                    412: #endif
                    413:        } else {
                    414:                if (opte.pg_pfnum)
                    415:                        panic("pagein pfnum");
                    416:                pgtrace(TR_SWAPIN);
                    417:                /*
                    418:                 * Fill from swap area.  Try to find adjacent
                    419:                 * pages to bring in also.
                    420:                 */
                    421:                v = kluster(p, v, pte, B_READ, &klsize,
                    422:                    (type == CTEXT) ? kltxt :
                    423:                    ((p->p_flag & SSEQL) ? klseql : klin), bn);
                    424:                splx(sk);
                    425:                /* THIS COULD BE COMPUTED INCREMENTALLY... */
                    426:                bncache = bn = vtod(p, v, &u.u_dmap, &u.u_smap);
                    427:        }
                    428: 
                    429:        distcl(pte);
                    430:        swerror = swap(p, bn, ptob(v), klsize * ctob(CLSIZE),
                    431:            B_READ, B_PGIN, vp, 0); 
                    432: #ifdef TRACE
                    433:        trace(TR_PGINDONE, vsave, u.u_procp->p_pid);
                    434: #endif
                    435: 
                    436:        /*
                    437:         * Instrumentation.
                    438:         */
                    439:        u.u_ru.ru_majflt++;
                    440:        cnt.v_pgin++;
                    441:        cnt.v_pgpgin += klsize * CLSIZE;
                    442: #ifdef PGINPROF
                    443:        a = vmtime(otime, olbolt, oicr) / 100;
                    444:        pgintime += a;
                    445:        if (a >= 0)
                    446:                vmfltmon(pmon, a, pmonmin, pres, NPMON);
                    447: #endif
                    448: 
                    449: skipswap:
                    450:        /*
                    451:         * Fix page table entries.
                    452:         *
                    453:         * Only page requested in is validated, and rest of pages
                    454:         * can be ``reclaimed''.  This allows system to reclaim prepaged pages
                    455:         * quickly if they are not used and memory is tight.
                    456:         */
                    457:        pte = vtopte(p, vsave);
                    458:        pte->pg_v = 1;
                    459: #ifdef REFBIT
                    460:        /*
                    461:         * Start with the page used so that pageout doesn't free it 
                    462:         * immediately.
                    463:         */
                    464:        pte->pg_u = 1;
                    465: #endif
                    466:        distcl(pte);
                    467:        if (type == CTEXT) {
                    468:                if (swerror) {
                    469:                        xinval(p->p_textp->x_vptr);
                    470:                } else {
                    471:                        distpte(p->p_textp, (unsigned)vtotp(p, vsave), pte);
                    472:                        if (opte.pg_fod)
                    473:                                p->p_textp->x_flag |= XWRIT;
                    474:                }
                    475:                wakeup((caddr_t)p->p_textp);
                    476:        }
                    477: 
                    478:        /*
                    479:         * Memall returned page(s) locked.  Unlock all
                    480:         * pages in cluster.  If locking pages for raw i/o
                    481:         * leave the page which was required to be paged in locked,
                    482:         * but still unlock others.
                    483:         * If text pages, hash into the cmap situation table.
                    484:         */
                    485:        pte = vtopte(p, v);
                    486:        for (i = 0; i < klsize; i++) {
                    487:                c = &cmap[pgtocm(pte->pg_pfnum)];
                    488:                c->c_intrans = 0;
                    489:                if (type == CTEXT && c->c_blkno == 0 && bncache && !nohash &&
                    490:                    !swerror) {
                    491:                        mhash(c, vp, bncache);
                    492:                        bncache += btodb(CLBYTES);
                    493:                }
                    494:                if (v != vsave || !dlyu)
                    495:                        MUNLOCK(c);
                    496:                if (v != vsave && type != CTEXT && preptofree &&
                    497:                    opte.pg_fod == 0) {
                    498:                        /*
                    499:                         * Throw pre-paged data/stack pages at the
                    500:                         * bottom of the free list; leave pg_u clear.
                    501:                         */
                    502:                        p->p_rssize -= CLSIZE;
                    503:                        memfree(pte, CLSIZE, 0);
                    504:                }
                    505: #ifdef REFBIT
                    506:                /*
                    507:                 * Text pages paged-in and allocated during the kluster
                    508:                 * must be validated, as they are now in the resident set.
                    509:                 */
                    510:                if (v != vsave && type == CTEXT) {
                    511:                        pte->pg_v = 1;
                    512:                        distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                    513:                }
                    514: #endif
                    515:                newptes(pte, v, CLSIZE);
                    516:                v += CLSIZE;
                    517:                pte += CLSIZE;
                    518:        }
                    519: 
                    520:        /*
                    521:         * All done.
                    522:         */
                    523:        p->p_flag &= ~SPAGE;
                    524: 
                    525:        /*
                    526:         * If process is declared fifo, memory is tight,
                    527:         * and this was a data page-in, free memory
                    528:         * klsdist pagein clusters away from the current fault.
                    529:         */
                    530:        if ((p->p_flag&SSEQL) && freemem < lotsfree && type == CDATA) {
                    531:                int k = (vtodp(p, vsave) / CLSIZE) / klseql;
                    532: #ifdef notdef
                    533:                if (vsave > u.u_vsave)
                    534:                        k -= klsdist;
                    535:                else
                    536:                        k += klsdist;
                    537:                dpageout(p, k * klseql * CLSIZE, klout*CLSIZE);
                    538:                u.u_vsave = vsave;
                    539: #else
                    540:                dpageout(p, (k - klsdist) * klseql * CLSIZE, klout*CLSIZE);
                    541:                dpageout(p, (k + klsdist) * klseql * CLSIZE, klout*CLSIZE);
                    542: #endif
                    543:        }
                    544: }
                    545: 
                    546: /*
                    547:  * Take away n pages of data space
                    548:  * starting at data page dp.
                    549:  * Used to take pages away from sequential processes.
                    550:  * Mimics pieces of code in pageout() below.
                    551:  */
                    552: dpageout(p, dp, n)
                    553:        struct proc *p;
                    554:        int dp, n;
                    555: {
                    556:        register struct cmap *c;
                    557:        int i, klsize;
                    558:        register struct pte *pte;
                    559:        unsigned v;
                    560:        daddr_t daddr;
                    561: 
                    562:        if (dp < 0) {
                    563:                n += dp;
                    564:                dp = 0;
                    565:        }
                    566:        if (dp + n > p->p_dsize)
                    567:                n = p->p_dsize - dp;
                    568:        for (i = 0; i < n; i += CLSIZE, dp += CLSIZE) {
                    569:                pte = dptopte(p, dp);
                    570:                if (pte->pg_fod || pte->pg_pfnum == 0)
                    571:                        continue;
                    572:                c = &cmap[pgtocm(pte->pg_pfnum)];
                    573:                if (c->c_lock || c->c_free)
                    574:                        continue;
                    575:                uncachecl(pte);
                    576:                if (pte->pg_v) {
                    577:                        pte->pg_v = 0;
                    578:                        if (anycl(pte, pg_m))
                    579:                                pte->pg_m = 1;
                    580:                        distcl(pte);
                    581:                        p->p_flag |= SPTECHG;
                    582:                }
                    583:                if (dirtycl(pte)) {
                    584:                        if (bswlist.av_forw == NULL)
                    585:                                continue;
                    586:                        MLOCK(c);
                    587:                        pte->pg_m = 0;
                    588:                        distcl(pte);
                    589:                        p->p_poip++;
                    590:                        v = kluster(p, dptov(p, dp), pte, B_WRITE,
                    591:                                &klsize, klout, (daddr_t)0);
                    592:                        /* THIS ASSUMES THAT p == u.u_procp */
                    593:                        daddr = vtod(p, v, &u.u_dmap, &u.u_smap);
                    594:                        (void) swap(p, daddr, ptob(v), klsize * ctob(CLSIZE),
                    595:                            B_WRITE, B_DIRTY, swapdev_vp, pte->pg_pfnum);
                    596:                } else {
                    597:                        if (c->c_gone == 0)
                    598:                                p->p_rssize -= CLSIZE;
                    599:                        memfree(pte, CLSIZE, 0);
                    600:                        cnt.v_seqfree += CLSIZE;
                    601:                }
                    602:        }
                    603: }
                    604:                    
                    605: unsigned maxdmap;
                    606: unsigned maxtsize;
                    607: 
                    608: /*
                    609:  * Setup the paging constants for the clock algorithm.
                    610:  * Called after the system is initialized and the amount of memory
                    611:  * and number of paging devices is known.
                    612:  *
                    613:  * Threshold constants are defined in machine/vmparam.h.
                    614:  */
                    615: vminit()
                    616: {
                    617: 
                    618:        /*
                    619:         * Lotsfree is threshold where paging daemon turns on.
                    620:         */
                    621:        if (lotsfree == 0) {
                    622:                lotsfree = LOTSFREE / NBPG;
                    623:                if (lotsfree > LOOPPAGES / LOTSFREEFRACT)
                    624:                        lotsfree = LOOPPAGES / LOTSFREEFRACT;
                    625:        }
                    626:        /*
                    627:         * Desfree is amount of memory desired free.
                    628:         * If less than this for extended period, do swapping.
                    629:         */
                    630:        if (desfree == 0) {
                    631:                desfree = DESFREE / NBPG;
                    632:                if (desfree > LOOPPAGES / DESFREEFRACT)
                    633:                        desfree = LOOPPAGES / DESFREEFRACT;
                    634:        }
                    635: 
                    636:        /*
                    637:         * Minfree is minimal amount of free memory which is tolerable.
                    638:         */
                    639:        if (minfree == 0) {
                    640:                minfree = MINFREE / NBPG;
                    641:                if (minfree > desfree / MINFREEFRACT)
                    642:                        minfree = desfree / MINFREEFRACT;
                    643:        }
                    644: 
                    645:        /*
                    646:         * Maxpgio thresholds how much paging is acceptable.
                    647:         * This figures that 2/3 busy on an arm is all that is
                    648:         * tolerable for paging.  We assume one operation per disk rev.
                    649:         */
                    650:        if (maxpgio == 0)
                    651:                maxpgio = (DISKRPM * 2) / 3;
                    652: 
                    653:        /*
                    654:         * Clock to scan using max of ~~10% of processor time for sampling,
                    655:         *     this estimated to allow maximum of 200 samples per second.
                    656:         * This yields a ``fastscan'' of roughly (with CLSIZE=2):
                    657:         *      <=1m    2m      3m      4m      8m
                    658:         *      5s      10s     15s     20s     40s
                    659:         */
                    660:        if (fastscan == 0)
                    661:                fastscan = 200;
                    662:        if (fastscan > LOOPPAGES / 5)
                    663:                fastscan = LOOPPAGES / 5;
                    664: 
                    665:        /*
                    666:         * Set slow scan time to 1/2 the fast scan time.
                    667:         */
                    668:        if (slowscan == 0)
                    669:                slowscan = fastscan / 2;
                    670: 
                    671:        /*
                    672:         * Calculate the swap allocation constants.
                    673:         */
                    674:         if (dmmin == 0) {
                    675:                 dmmin = DMMIN;
                    676:                if (dmmin < CLBYTES/DEV_BSIZE)
                    677:                        dmmin = CLBYTES/DEV_BSIZE;
                    678:        }
                    679:         if (dmmax == 0) {
                    680:                 dmmax = DMMAX;
                    681:                while (dmapsize(dmmin, dmmax / 2) >= MAXDSIZ && dmmax > dmmin)
                    682:                        dmmax /= 2;
                    683:        }
                    684:        maxdmap = dmapsize(dmmin, dmmax);
                    685:         if (dmtext == 0)
                    686:                 dmtext = DMTEXT;
                    687:         if (dmtext > dmmax)
                    688:                 dmtext = dmmax;
                    689:        if (maxtsize == 0)
                    690:                maxtsize = MAXTSIZ;
                    691:        if (maxtsize > dtob(NXDAD * dmtext))
                    692:                maxtsize = dtob(NXDAD * dmtext);
                    693: 
                    694:        /*
                    695:         * Set up the initial limits on process VM.
                    696:         * Set the maximum resident set size to be all
                    697:         * of (reasonably) available memory.  This causes
                    698:         * any single, large process to start random page
                    699:         * replacement once it fills memory.
                    700:         */
                    701:         u.u_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ;
                    702:         u.u_rlimit[RLIMIT_STACK].rlim_max = MIN(MAXSSIZ, maxdmap);
                    703:         u.u_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ;
                    704:         u.u_rlimit[RLIMIT_DATA].rlim_max = MIN(MAXDSIZ, maxdmap);
                    705:        u.u_rlimit[RLIMIT_RSS].rlim_cur = u.u_rlimit[RLIMIT_RSS].rlim_max =
                    706:                ctob(LOOPPAGES - desfree);
                    707:        proc[0].p_maxrss = LOOPPAGES - desfree;
                    708: }
                    709: 
                    710: dmapsize(dmin, dmax)
                    711:        int dmin, dmax;
                    712: {
                    713:        register int i, blk, size = 0;
                    714: 
                    715:        blk = dmin;
                    716:        for (i = 0; i < NDMAP; i++) {
                    717:                size += blk;
                    718:                if (blk < dmax)
                    719:                        blk *= 2;
                    720:        }
                    721:        return (dtob(size));
                    722: }
                    723: 
                    724: int    pushes;
                    725: 
                    726: #define        FRONT   1
                    727: #define        BACK    2
                    728: 
                    729: /*
                    730:  * The page out daemon, which runs as process 2.
                    731:  *
                    732:  * As long as there are at least lotsfree pages,
                    733:  * this process is not run.  When the number of free
                    734:  * pages stays in the range desfree to lotsfree,
                    735:  * this daemon runs through the pages in the loop
                    736:  * at a rate determined in vmsched().  Pageout manages
                    737:  * two hands on the clock.  The front hand moves through
                    738:  * memory, clearing the valid bit (simulating a reference bit),
                    739:  * and stealing pages from procs that are over maxrss.
                    740:  * The back hand travels a distance behind the front hand,
                    741:  * freeing the pages that have not been referenced in the time
                    742:  * since the front hand passed.  If modified, they are pushed to
                    743:  * swap before being freed.
                    744:  */
                    745: pageout()
                    746: {
                    747:        register int count;
                    748:        register int maxhand = pgtocm(maxfree);
                    749:        register int fronthand, backhand;
                    750: 
                    751:        /*
                    752:         * Set the two clock hands to be separated by a reasonable amount,
                    753:         * but no more than 360 degrees apart.
                    754:         */
                    755:        backhand = 0 / CLBYTES;
                    756:        fronthand = HANDSPREAD / CLBYTES;
                    757:        if (fronthand >= maxhand)
                    758:                fronthand = maxhand - 1;
                    759: 
                    760: loop:
                    761:        /*
                    762:         * Before sleeping, look to see if there are any swap I/O headers
                    763:         * in the ``cleaned'' list that correspond to dirty
                    764:         * pages that have been pushed asynchronously. If so,
                    765:         * empty the list by calling cleanup().
                    766:         *
                    767:         * N.B.: We guarantee never to block while the cleaned list is nonempty.
                    768:         */
                    769:        (void) splbio();
                    770:        if (bclnlist != NULL) {
                    771:                (void) spl0();
                    772:                cleanup();
                    773:                goto loop;
                    774:        }
                    775:        sleep((caddr_t)&proc[2], PSWP+1);
                    776:        (void) spl0();
                    777:        count = 0;
                    778:        pushes = 0;
                    779:        while (nscan < desscan && freemem < lotsfree) {
                    780:                /*
                    781:                 * If checkpage manages to add a page to the free list,
                    782:                 * we give ourselves another couple of trips around the loop.
                    783:                 */
                    784:                if (checkpage(fronthand, FRONT))
                    785:                        count = 0;
                    786:                if (checkpage(backhand, BACK))
                    787:                        count = 0;
                    788:                cnt.v_scan++;
                    789:                nscan++;
                    790:                if (++backhand >= maxhand)
                    791:                        backhand = 0;
                    792:                if (++fronthand >= maxhand) {
                    793:                        fronthand = 0;
                    794:                        cnt.v_rev++;
                    795:                        if (count > 2) {
                    796:                                /*
                    797:                                 * Extremely unlikely, but we went around
                    798:                                 * the loop twice and didn't get anywhere.
                    799:                                 * Don't cycle, stop till the next clock tick.
                    800:                                 */
                    801:                                goto loop;
                    802:                        }
                    803:                        count++;
                    804:                }
                    805:        }
                    806:        goto loop;
                    807: }
                    808: 
                    809: /*
                    810:  * An iteration of the clock pointer (hand) around the loop.
                    811:  * Look at the page at hand.  If it is a
                    812:  * locked (for physical i/o e.g.), system (u., page table)
                    813:  * or free, then leave it alone.
                    814:  * Otherwise, if we are running the front hand,
                    815:  * invalidate the page for simulation of the reference bit.
                    816:  * If the proc is over maxrss, we take it.
                    817:  * If running the back hand, check whether the page
                    818:  * has been reclaimed.  If not, free the page,
                    819:  * pushing it to disk first if necessary.
                    820:  */
                    821: checkpage(hand, whichhand)
                    822:        int hand, whichhand;
                    823: {
                    824:        register struct proc *rp;
                    825:        register struct text *xp;
                    826:        register struct cmap *c;
                    827:        register struct pte *pte;
                    828:        swblk_t daddr;
                    829:        unsigned v;
                    830:        int klsize;
                    831: 
                    832: top:
                    833:        /*
                    834:         * Find a process and text pointer for the
                    835:         * page, and a virtual page number in either the
                    836:         * process or the text image.
                    837:         */
                    838:        c = &cmap[hand];
                    839:        if (c->c_lock || c->c_free)
                    840:                return (0);
                    841:        switch (c->c_type) {
                    842: 
                    843:        case CSYS:
                    844:                return (0);
                    845: 
                    846:        case CTEXT:
                    847:                xp = &text[c->c_ndx];
                    848:                rp = xp->x_caddr;
                    849:                v = tptov(rp, c->c_page);
                    850:                pte = tptopte(rp, c->c_page);
                    851:                break;
                    852: 
                    853:        case CDATA:
                    854:        case CSTACK:
                    855:                rp = &proc[c->c_ndx];
                    856:                while (rp->p_flag & SNOVM)
                    857:                        rp = rp->p_xlink;
                    858:                xp = rp->p_textp;
                    859:                if (c->c_type == CDATA) {
                    860:                        v = dptov(rp, c->c_page);
                    861:                        pte = dptopte(rp, c->c_page);
                    862:                } else {
                    863:                        v = sptov(rp, c->c_page);
                    864:                        pte = sptopte(rp, c->c_page);
                    865:                }
                    866:                break;
                    867:        }
                    868:        if (pte->pg_pfnum != cmtopg(hand))
                    869:                panic("bad c_page");
                    870: #ifdef REFBIT
                    871:        /*
                    872:         * If any processes attached to the text page have used
                    873:         * it, then mark this one used and on the following
                    874:         * distpte, they will all be marked used.
                    875:         */
                    876:        if (c->c_type == CTEXT && tanyu(xp, vtotp(rp, v))) 
                    877:                pte->pg_u = 1;
                    878:        /*
                    879:         * If page is referenced, clear its reference bit.
                    880:         * If page is not referenced, clear valid bit
                    881:         * and add it to the free list.
                    882:         */
                    883:        uncachecl(pte);
                    884:        if (anycl(pte, pg_u))
                    885: #else
                    886:        /*
                    887:         * If page is valid; make invalid but reclaimable.
                    888:         * If this pte is not valid, then it must be reclaimable
                    889:         * and we can add it to the free list.
                    890:         */
                    891:        if (pte->pg_v)
                    892: #endif
                    893:        {
                    894:                if (whichhand == BACK)
                    895:                        return (0);
                    896: #ifdef REFBIT
                    897:                pte->pg_u = 0;
                    898: #else
                    899:                pte->pg_v = 0;
                    900:                rp->p_flag |= SPTECHG;
                    901: #endif
                    902:                if (anycl(pte, pg_m))
                    903:                        pte->pg_m = 1;
                    904:                distcl(pte);
                    905:                if (c->c_type == CTEXT)
                    906:                        distpte(xp, (unsigned)vtotp(rp, v), pte);
                    907:                if ((rp->p_flag & (SSEQL|SUANOM)) == 0 &&
                    908:                    rp->p_rssize <= rp->p_maxrss)
                    909:                        return (0);
                    910:        }
                    911:        if (c->c_type != CTEXT) {
                    912:                /*
                    913:                 * Guarantee a minimal investment in data
                    914:                 * space for jobs in balance set.
                    915:                 */
                    916:                if (rp->p_rssize < saferss - rp->p_slptime)
                    917:                        return (0);
                    918:        }
                    919: 
                    920:        /*
                    921:         * If the page is currently dirty, we
                    922:         * have to arrange to have it cleaned before it
                    923:         * can be freed.  We mark it clean immediately.
                    924:         * If it is reclaimed while being pushed, then modified
                    925:         * again, we are assured of the correct order of 
                    926:         * writes because we lock the page during the write.  
                    927:         * This guarantees that a swap() of this process (and
                    928:         * thus this page), initiated in parallel, will,
                    929:         * in fact, push the page after us.
                    930:         *
                    931:         * The most general worst case here would be for
                    932:         * a reclaim, a modify and a swapout to occur
                    933:         * all before the single page transfer completes.
                    934:         */
                    935:        if (dirtycl(pte)) {
                    936:                /*
                    937:                 * If the process is being swapped out
                    938:                 * or about to exit, do not bother with its
                    939:                 * dirty pages
                    940:                 */
                    941:                if (rp->p_flag & (SLOCK|SWEXIT))
                    942:                        return (0);
                    943:                /*
                    944:                 * Limit pushes to avoid saturating
                    945:                 * pageout device.
                    946:                 */
                    947:                if (pushes > maxpgio / RATETOSCHEDPAGING)
                    948:                        return (0);
                    949:                pushes++;
                    950: 
                    951:                /*
                    952:                 * Now carefully make sure that there will
                    953:                 * be a header available for the push so that
                    954:                 * we will not block waiting for a header in
                    955:                 * swap().  The reason this is important is
                    956:                 * that we (proc[2]) are the one who cleans
                    957:                 * dirty swap headers and we could otherwise
                    958:                 * deadlock waiting for ourselves to clean
                    959:                 * swap headers.  The sleep here on &proc[2]
                    960:                 * is actually (effectively) a sleep on both
                    961:                 * ourselves and &bswlist, and this is known
                    962:                 * to swdone and swap in vm_swp.c.  That is,
                    963:                 * &proc[2] will be awakened both when dirty
                    964:                 * headers show up and also to get the pageout
                    965:                 * daemon moving.
                    966:                 */
                    967: loop2:
                    968:                (void) splbio();
                    969:                if (bclnlist != NULL) {
                    970:                        (void) spl0();
                    971:                        cleanup();
                    972:                        goto loop2;
                    973:                }
                    974:                if (bswlist.av_forw == NULL) {
                    975:                        bswlist.b_flags |= B_WANTED;
                    976:                        sleep((caddr_t)&proc[2], PSWP+2);
                    977:                        (void) spl0();
                    978:                        /*
                    979:                         * Page disposition may have changed
                    980:                         * since process may have exec'ed,
                    981:                         * forked, exited or just about
                    982:                         * anything else... try this page
                    983:                         * frame again, from the top.
                    984:                         */
                    985:                        goto top;
                    986:                }
                    987:                (void) spl0();
                    988: 
                    989:                MLOCK(c);
                    990:                uaccess(rp, Pushmap, &pushutl);
                    991:                /*
                    992:                 * Now committed to pushing the page...
                    993:                 */
                    994: #ifdef REFBIT
                    995:                pte->pg_v = 0;
                    996:                rp->p_flag |= SPTECHG;
                    997: #endif
                    998:                pte->pg_m = 0;
                    999:                distcl(pte);
                   1000:                if (c->c_type == CTEXT)  {
                   1001:                        xp->x_poip++;
                   1002:                        distpte(xp, (unsigned)vtotp(rp, v), pte);
                   1003:                } else
                   1004:                        rp->p_poip++;
                   1005:                v = kluster(rp, v, pte, B_WRITE, &klsize, klout, (daddr_t)0);
                   1006:                if (klsize == 0)
                   1007:                        panic("pageout klsize");
                   1008:                daddr = vtod(rp, v, &pushutl.u_dmap, &pushutl.u_smap);
                   1009:                (void) swap(rp, daddr, ptob(v), klsize * ctob(CLSIZE),
                   1010:                    B_WRITE, B_DIRTY, swapdev_vp, pte->pg_pfnum);
                   1011:                /*
                   1012:                 * The cleaning of this page will be
                   1013:                 * completed later, in cleanup() called
                   1014:                 * (synchronously) by us (proc[2]).  In
                   1015:                 * the meantime, the page frame is locked
                   1016:                 * so no havoc can result.
                   1017:                 */
                   1018:                return (1);     /* well, it'll be free soon */
                   1019:        }
                   1020:        /*
                   1021:         * Propagate valid bit changes.
                   1022:         * Decrement the resident set size of the current
                   1023:         * text object/process, and put the page in the
                   1024:         * free list.  Don't detach the page yet;
                   1025:         * it may yet have a chance to be reclaimed from
                   1026:         * the free list.
                   1027:         */
                   1028: #ifdef REFBIT
                   1029:        pte->pg_v = 0;
                   1030:        distcl(pte);
                   1031:        if (c->c_type == CTEXT)
                   1032:                distpte(xp, (unsigned)vtotp(rp, v), pte);
                   1033:        else
                   1034:                rp->p_flag |= SPTECHG;
                   1035: #endif
                   1036:        if (c->c_gone == 0)
                   1037:                if (c->c_type == CTEXT)
                   1038:                        xp->x_rssize -= CLSIZE;
                   1039:                else
                   1040:                        rp->p_rssize -= CLSIZE;
                   1041:        memfree(pte, CLSIZE, 0);
                   1042:        cnt.v_dfree += CLSIZE;
                   1043:        return (1);             /* freed a page! */
                   1044: }
                   1045: 
                   1046: /*
                   1047:  * Process the ``cleaned'' list.
                   1048:  *
                   1049:  * Scan through the linked list of swap I/O headers
                   1050:  * and free the corresponding pages that have been
                   1051:  * cleaned by being written back to the paging area.
                   1052:  * If the page has been reclaimed during this time,
                   1053:  * we do not free the page.  As they are processed,
                   1054:  * the swap I/O headers are removed from the cleaned
                   1055:  * list and inserted into the free list.
                   1056:  */
                   1057: cleanup()
                   1058: {
                   1059:        register struct buf *bp;
                   1060:        register struct proc *rp;
                   1061:        register struct text *xp;
                   1062:        register struct cmap *c;
                   1063:        register struct pte *pte;
                   1064:        struct pte *upte;
                   1065:        unsigned pf;
                   1066:        register int i;
                   1067:        int s, center;
                   1068: 
                   1069:        for (;;) {
                   1070:                s = splbio();
                   1071:                if ((bp = bclnlist) == 0)
                   1072:                        break;
                   1073:                bclnlist = bp->av_forw;
                   1074:                splx(s);
                   1075:                pte = vtopte(&proc[2], btop(bp->b_un.b_addr));
                   1076:                center = 0;
                   1077:                for (i = 0; i < bp->b_bcount; i += CLSIZE * NBPG) {
                   1078:                        pf = pte->pg_pfnum;
                   1079:                        c = &cmap[pgtocm(pf)];
                   1080:                        MUNLOCK(c);
                   1081:                        if (pf != bp->b_pfcent) {
                   1082:                                if (c->c_gone) {
                   1083:                                        memfree(pte, CLSIZE, 0);
                   1084:                                        cnt.v_dfree += CLSIZE;
                   1085:                                }
                   1086:                                goto skip;
                   1087:                        }
                   1088:                        center++;
                   1089:                        switch (c->c_type) {
                   1090: 
                   1091:                        case CSYS:
                   1092:                                panic("cleanup CSYS");
                   1093: 
                   1094:                        case CTEXT:
                   1095:                                xp = &text[c->c_ndx];
                   1096:                                xp->x_poip--;
                   1097:                                if (xp->x_poip == 0)
                   1098:                                        wakeup((caddr_t)&xp->x_poip);
                   1099:                                break;
                   1100: 
                   1101:                        case CDATA:
                   1102:                        case CSTACK:
                   1103:                                rp = &proc[c->c_ndx];
                   1104:                                while (rp->p_flag & SNOVM)
                   1105:                                        rp = rp->p_xlink;
                   1106:                                rp->p_poip--;
                   1107:                                if (rp->p_poip == 0)
                   1108:                                        wakeup((caddr_t)&rp->p_poip);
                   1109:                                break;
                   1110:                        }
                   1111:                        if (c->c_gone == 0) {
                   1112:                                switch (c->c_type) {
                   1113: 
                   1114:                                case CTEXT:
                   1115:                                        upte = tptopte(xp->x_caddr, c->c_page);
                   1116:                                        break;
                   1117: 
                   1118:                                case CDATA:
                   1119:                                        upte = dptopte(rp, c->c_page);
                   1120:                                        break;
                   1121: 
                   1122:                                case CSTACK:
                   1123:                                        upte = sptopte(rp, c->c_page);
                   1124:                                        break;
                   1125:                                }
                   1126:                                if (upte->pg_v)
                   1127:                                        goto skip;
                   1128:                                if (c->c_type == CTEXT)
                   1129:                                        xp->x_rssize -= CLSIZE;
                   1130:                                else
                   1131:                                        rp->p_rssize -= CLSIZE;
                   1132:                        }
                   1133:                        memfree(pte, CLSIZE, 0);
                   1134:                        cnt.v_dfree += CLSIZE;
                   1135: skip:
                   1136:                        pte += CLSIZE;
                   1137:                }
                   1138:                if (center != 1)
                   1139:                        panic("cleanup center");
                   1140:                bp->b_flags = 0;
                   1141:                bp->av_forw = bswlist.av_forw;
                   1142:                bswlist.av_forw = bp;
                   1143:                if (bp->b_vp)
                   1144:                        brelvp(bp);
                   1145:                if (bswlist.b_flags & B_WANTED) {
                   1146:                        bswlist.b_flags &= ~B_WANTED;
                   1147:                        wakeup((caddr_t)&bswlist);
                   1148:                }
                   1149:        }
                   1150:        splx(s);
                   1151: }
                   1152: 
                   1153: /*
                   1154:  * Kluster locates pages adjacent to the argument pages
                   1155:  * that are immediately available to include in the pagein/pageout,
                   1156:  * and given the availability of memory includes them.
                   1157:  * It knows that the process image is contiguous in chunks;
                   1158:  * an assumption here is that CLSIZE * KLMAX is a divisor of dmmin,
                   1159:  * so that by looking at KLMAX chunks of pages, all such will
                   1160:  * necessarily be mapped swap contiguous.
                   1161:  */
                   1162: int    noklust;
                   1163: int    klicnt[KLMAX];
                   1164: int    klocnt[KLMAX];
                   1165: 
                   1166: kluster(p, v, pte0, rw, pkl, klsize, bn0)
                   1167:        register struct proc *p;
                   1168:        unsigned v;
                   1169:        struct pte *pte0;
                   1170:        int rw;
                   1171:        register int *pkl;
                   1172:        int klsize;
                   1173:        daddr_t bn0;
                   1174: {
                   1175:        int type, cl, clmax;
                   1176:        int kloff, k, klmax;
                   1177:        register struct pte *pte;
                   1178:        int klback, klforw;
                   1179:        int i;
                   1180:        unsigned v0;
                   1181:        daddr_t bn;
                   1182:        register struct cmap *c;
                   1183: 
                   1184:        if (rw == B_READ)
                   1185:                klicnt[0]++;
                   1186:        else
                   1187:                klocnt[0]++;
                   1188:        *pkl = 1;
                   1189:        if (noklust || klsize <= 1 || klsize > KLMAX || (klsize & (klsize - 1)))
                   1190:                return (v);
                   1191:        if (rw == B_READ && freemem < CLSIZE * KLMAX)
                   1192:                return (v);
                   1193:        if (isassv(p, v)) {
                   1194:                type = CSTACK;
                   1195:                cl = vtosp(p, v) / CLSIZE;
                   1196:                clmax = p->p_ssize / CLSIZE;
                   1197:        } else if (isadsv(p, v)) {
                   1198:                type = CDATA;
                   1199:                cl = vtodp(p, v) / CLSIZE;
                   1200:                clmax = p->p_dsize / CLSIZE;
                   1201:        } else {
                   1202:                type = CTEXT;
                   1203:                cl = vtotp(p, v) / CLSIZE;
                   1204:                clmax = p->p_textp->x_size / CLSIZE;
                   1205:        }
                   1206:        kloff = cl & (klsize - 1);
                   1207:        pte = pte0;
                   1208:        bn = bn0;
                   1209:        for (k = kloff; --k >= 0;) {
                   1210:                if (type == CSTACK)
                   1211:                        pte += CLSIZE;
                   1212:                else
                   1213:                        pte -= CLSIZE;
                   1214:                if (type == CTEXT && rw == B_READ && bn) {
                   1215:                        bn -= btodb(CLBYTES);
                   1216:                        if (mfind(swapdev_vp, bn))
                   1217:                                break;
                   1218:                }
                   1219:                if (!klok(pte, rw))
                   1220:                        break;
                   1221:        }
                   1222:        klback = (kloff - k) - 1;
                   1223:        pte = pte0;
                   1224:        if ((cl - kloff) + klsize > clmax)
                   1225:                klmax = clmax - (cl - kloff);
                   1226:        else
                   1227:                klmax = klsize;
                   1228:        bn = bn0;
                   1229:        for (k = kloff; ++k < klmax;) {
                   1230:                if (type == CSTACK)
                   1231:                        pte -= CLSIZE;
                   1232:                else
                   1233:                        pte += CLSIZE;
                   1234:                if (type == CTEXT && rw == B_READ && bn) {
                   1235:                        bn += btodb(CLBYTES);
                   1236:                        if (mfind(swapdev_vp, bn))
                   1237:                                break;
                   1238:                }
                   1239:                if (!klok(pte, rw))
                   1240:                        break;
                   1241:        }
                   1242:        klforw = (k - kloff) - 1;
                   1243:        if (klforw + klback == 0)
                   1244:                return (v);
                   1245:        pte = pte0;
                   1246:        if (type == CSTACK) {
                   1247:                pte -= klforw * CLSIZE;
                   1248:                v -= klforw * CLSIZE;
                   1249:        } else {
                   1250:                pte -= klback * CLSIZE;
                   1251:                v -= klback * CLSIZE;
                   1252:        }
                   1253:        *pkl = klforw + klback + 1;
                   1254:        if (rw == B_READ)
                   1255:                klicnt[0]--, klicnt[*pkl - 1]++;
                   1256:        else
                   1257:                klocnt[0]--, klocnt[*pkl - 1]++;
                   1258:        v0 = v;
                   1259:        for (i = 0; i < *pkl; i++) {
                   1260:                if (pte == pte0)
                   1261:                        goto cont;
                   1262:                if (rw == B_WRITE) {
                   1263:                        c = &cmap[pgtocm(pte->pg_pfnum)];
                   1264:                        MLOCK(c);
                   1265:                        pte->pg_m = 0;
                   1266:                        distcl(pte);
                   1267:                        if (type == CTEXT)
                   1268:                                distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                   1269:                } else {
                   1270:                        struct pte opte;
                   1271: 
                   1272:                        opte = *pte;
                   1273:                        if (memall(pte, CLSIZE, p, type) == 0)
                   1274:                                panic("kluster");
                   1275:                        pte->pg_prot = opte.pg_prot;
                   1276:                        cmap[pgtocm(pte->pg_pfnum)].c_intrans = 1;
                   1277:                        distcl(pte);
                   1278:                        if (type == CTEXT) {
                   1279:                                p->p_textp->x_rssize += CLSIZE;
                   1280:                                distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                   1281:                        } else
                   1282:                                p->p_rssize += CLSIZE;
                   1283:                        distcl(pte);
                   1284:                }
                   1285: cont:
                   1286:                pte += CLSIZE;
                   1287:                v += CLSIZE;
                   1288:        }
                   1289:        return (v0);
                   1290: }
                   1291: 
                   1292: klok(pte, rw)
                   1293:        register struct pte *pte;
                   1294:        int rw;
                   1295: {
                   1296:        register struct cmap *c;
                   1297: 
                   1298:        if (rw == B_WRITE) {
                   1299:                if (pte->pg_fod)
                   1300:                        return (0);
                   1301:                if (pte->pg_pfnum == 0)
                   1302:                        return (0);
                   1303:                c = &cmap[pgtocm(pte->pg_pfnum)];
                   1304:                if (c->c_lock || c->c_intrans)
                   1305:                        return (0);
                   1306:                uncachecl(pte);
                   1307:                if (!dirtycl(pte))
                   1308:                        return (0);
                   1309:                return (1);
                   1310:        } else {
                   1311:                if (pte->pg_fod)
                   1312:                        return (0);
                   1313:                if (pte->pg_pfnum)
                   1314:                        return (0);
                   1315:                return (1);
                   1316:        }
                   1317: }
                   1318: 
                   1319: /*
                   1320:  * Fodkluster locates pages adjacent to the argument pages
                   1321:  * that are immediately available to include in the pagein,
                   1322:  * and given the availability of memory includes them.
                   1323:  * It wants to page in a file system block if it can.
                   1324:  */
                   1325: int    nofodklust = 0;
                   1326: int    fodklcnt[KLMAX];
                   1327: 
                   1328: fodkluster(p, v0, pte0, pkl, vp, pbn)
                   1329:        register struct proc *p;
                   1330:        unsigned v0;
                   1331:        struct pte *pte0;
                   1332:        int *pkl;
                   1333:        struct vnode *vp;
                   1334:        daddr_t *pbn;
                   1335: {
                   1336:        register struct pte *pte;
                   1337:        register struct fpte *fpte;
                   1338:        register daddr_t bn;
                   1339:        daddr_t bnswap;
                   1340:        unsigned v, vmin, vmax;
                   1341:        register int klsize;
                   1342:        int klback, type, i;
                   1343: 
                   1344:        fodklcnt[0]++;
                   1345:        *pkl = 1;
                   1346:        if (freemem < KLMAX || nofodklust)
                   1347:                return (v0);
                   1348:        if (isatsv(p, v0)) {
                   1349:                type = CTEXT;
                   1350:                vmin = tptov(p, 0);
                   1351:                vmax = tptov(p, clrnd(p->p_tsize) - CLSIZE);
                   1352:        } else {
                   1353:                type = CDATA;
                   1354:                vmin = dptov(p, 0);
                   1355:                vmax = dptov(p, clrnd(p->p_dsize) - CLSIZE);
                   1356:        }
                   1357:        fpte = (struct fpte *)pte0;
                   1358:        bn = *pbn;
                   1359:        v = v0;
                   1360:        for (klsize = 1; klsize < KLMAX; klsize++) {
                   1361:                if (v <= vmin)
                   1362:                        break;
                   1363:                v -= CLSIZE;
                   1364:                fpte -= CLSIZE;
                   1365:                if (fpte->pg_fod == 0)
                   1366:                        break;
                   1367:                bn -= btodb(CLBYTES);
                   1368:                if (fpte->pg_blkno != bn)
                   1369:                        break;
                   1370:                if (type == CTEXT) {
                   1371:                        if (mfind(vp, bn))
                   1372:                                break;
                   1373:                        /*
                   1374:                         * Flush any previous text page use of this
                   1375:                         * swap device block.
                   1376:                         */
                   1377:                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                   1378:                        munhash(swapdev_vp, bnswap);
                   1379:                }
                   1380:        }
                   1381:        klback = klsize - 1;
                   1382:        fpte = (struct fpte *)pte0;
                   1383:        bn = *pbn;
                   1384:        v = v0;
                   1385:        for (; klsize < KLMAX; klsize++) {
                   1386:                v += CLSIZE;
                   1387:                if (v > vmax)
                   1388:                        break;
                   1389:                fpte += CLSIZE;
                   1390:                if (fpte->pg_fod == 0)
                   1391:                        break;
                   1392:                bn += btodb(CLBYTES);
                   1393:                if (fpte->pg_blkno != bn)
                   1394:                        break;
                   1395:                if (type == CTEXT) {
                   1396:                        if (mfind(vp, bn))
                   1397:                                break;
                   1398:                        /*
                   1399:                         * Flush any previous text page use of this
                   1400:                         * swap device block.
                   1401:                         */
                   1402:                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                   1403:                        munhash(swapdev_vp, bnswap);
                   1404:                }
                   1405:        }
                   1406:        if (klsize == 1)
                   1407:                return (v0);
                   1408:        pte = pte0;
                   1409:        pte -= klback * CLSIZE;
                   1410:        v0 -= klback * CLSIZE;
                   1411:        *pbn -= klback * btodb(CLBYTES);
                   1412:        *pkl = klsize;
                   1413:        fodklcnt[0]--; fodklcnt[klsize - 1]++;
                   1414:        v = v0;
                   1415:        for (i = 0; i < klsize; i++) {
                   1416:                if (pte != pte0) {
                   1417:                        struct pte opte;
                   1418:                        int pf;
                   1419: 
                   1420:                        opte = *pte;
                   1421:                        if (memall(pte, CLSIZE, p, type) == 0)
                   1422:                                panic("fodkluster");
                   1423:                        pte->pg_prot = opte.pg_prot;
                   1424:                        pf = pte->pg_pfnum;
                   1425:                        pte->pg_m = 1;
                   1426:                        cmap[pgtocm(pf)].c_intrans = 1;
                   1427:                        distcl(pte);
                   1428:                        if (type == CTEXT) {
                   1429:                                p->p_textp->x_rssize += CLSIZE;
                   1430:                                distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
                   1431:                        } else
                   1432:                                p->p_rssize += CLSIZE;
                   1433:                        distcl(pte);
                   1434:                }
                   1435:                pte += CLSIZE;
                   1436:                v += CLSIZE;
                   1437:        }
                   1438:        return (v0);
                   1439: }
                   1440: 
                   1441: #ifdef REFBIT
                   1442: /*
                   1443:  * Examine the reference bits in the pte's of all
                   1444:  * processes linked to a particular text segment. 
                   1445:  */
                   1446: tanyu(xp, tp)
                   1447:        struct text *xp;
                   1448:        register tp;
                   1449: {
                   1450:        register struct proc *p;
                   1451:        register struct pte *pte;
                   1452: 
                   1453:        for (p = xp->x_caddr; p; p = p->p_xlink) {
                   1454:                pte = tptopte(p, tp);
                   1455:                uncache(pte);
                   1456:                if (anycl(pte, pg_u))
                   1457:                        return (1);
                   1458:        }
                   1459:        return (0);
                   1460: }
                   1461: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.