BSD 4_3_Tahoe release
[unix-history] / usr / src / sys / sys / vm_page.c
index 6a1855f..90351a0 100644 (file)
@@ -3,12 +3,9 @@
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)vm_page.c   7.1 (Berkeley) 6/5/86
+ *     @(#)vm_page.c   7.7 (Berkeley) 8/23/87
  */
 
  */
 
-#include "../machine/reg.h"
-#include "../machine/pte.h"
-
 #include "param.h"
 #include "systm.h"
 #include "inode.h"
 #include "param.h"
 #include "systm.h"
 #include "inode.h"
 #include "file.h"
 #include "trace.h"
 
 #include "file.h"
 #include "trace.h"
 
+#include "../machine/cpu.h"
+#include "../machine/reg.h"
+#include "../machine/pte.h"
+#include "../machine/mtpr.h"
+
+#ifdef tahoe
+#define REFBIT
+#if CLSIZE == 1
+#define uncachecl(pte) uncache(pte)
+#endif
+#if CLSIZE == 2
+#define uncachecl(pte) uncache(pte), uncache((pte)+1)
+#endif
+#if CLSIZE > 2
+#define uncachecl(pte) { \
+       register ii; \
+       for (ii = 0; ii < CLSIZE; ii++) \
+               uncache((pte) + ii); \
+}
+#endif
+
+#else tahoe
+#define uncachecl(pte) /* nothing */
+#endif
+
 int    nohash = 0;
 /*
  * Handle a page fault.
 int    nohash = 0;
 /*
  * Handle a page fault.
@@ -85,7 +107,6 @@ pagein(virtaddr, dlyu)
        int si, sk;
        int swerror = 0;
 #ifdef PGINPROF
        int si, sk;
        int swerror = 0;
 #ifdef PGINPROF
-#include "../vax/mtpr.h"
        int otime, olbolt, oicr, s;
        long a;
 
        int otime, olbolt, oicr, s;
        long a;
 
@@ -158,6 +179,7 @@ valid:
                } else
                        pgtrace(TR_RECLAIM);
                splx(si);
                } else
                        pgtrace(TR_RECLAIM);
                splx(si);
+               uncachecl(pte);
                pte->pg_v = 1;
                if (anycl(pte, pg_m))
                        pte->pg_m = 1;
                pte->pg_v = 1;
                if (anycl(pte, pg_m))
                        pte->pg_m = 1;
@@ -201,8 +223,6 @@ valid:
                fileno = ((struct fpte *)pte)->pg_fileno;
                bn = ((struct fpte *)pte)->pg_blkno;
                bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                fileno = ((struct fpte *)pte)->pg_fileno;
                bn = ((struct fpte *)pte)->pg_blkno;
                bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
-               if (fileno > PG_FMAX)
-                       panic("pagein pg_fileno");
                if (fileno == PG_FTEXT) {
                        if (p->p_textp == 0)
                                panic("pagein PG_FTEXT");
                if (fileno == PG_FTEXT) {
                        if (p->p_textp == 0)
                                panic("pagein PG_FTEXT");
@@ -211,8 +231,6 @@ valid:
                } else if (fileno == PG_FZERO) {
                        dev = swapdev;
                        bncache = bnswap;
                } else if (fileno == PG_FZERO) {
                        dev = swapdev;
                        bncache = bnswap;
-               } else {
-                       panic("pagein");        /* can't happen */
                }
        }
        klsize = 1;
                }
        }
        klsize = 1;
@@ -267,9 +285,7 @@ valid:
                        cnt.v_pgrec++;
                        u.u_ru.ru_minflt++;
                        if (dev != swapdev) {
                        cnt.v_pgrec++;
                        u.u_ru.ru_minflt++;
                        if (dev != swapdev) {
-                               c = mfind(swapdev, bnswap);
-                               if (c)
-                                       munhash(swapdev, bnswap);
+                               munhash(swapdev, bnswap);
                                pte->pg_m = 1;
                        }
                        splx(si);
                                pte->pg_m = 1;
                        }
                        splx(si);
@@ -329,21 +345,20 @@ valid:
                         * Flush any previous text page use of this
                         * swap device block.
                         */
                         * Flush any previous text page use of this
                         * swap device block.
                         */
-                       si = splimp();
-                       if (type == CTEXT) {
-                               c = mfind(swapdev, bnswap);
-                               if (c)
-                                       munhash(swapdev, bnswap);
-                       }
-                       splx(si);
+                       if (type == CTEXT)
+                               munhash(swapdev, bnswap);
                        /*
                         * If zero fill, short-circuit hard work
                         * by just clearing pages.
                         */
                        if (fileno == PG_FZERO) {
                                pgtrace(TR_ZFOD);
                        /*
                         * If zero fill, short-circuit hard work
                         * by just clearing pages.
                         */
                        if (fileno == PG_FZERO) {
                                pgtrace(TR_ZFOD);
-                               for (i = 0; i < CLSIZE; i++)
+                               for (i = 0; i < CLSIZE; i++) {
                                        clearseg(pf+i);
                                        clearseg(pf+i);
+#if defined(tahoe)
+                                       mtpr(P1DC, (int)virtaddr + i * NBPG);
+#endif
+                               }
                                if (type != CTEXT)
                                        cnt.v_zfod += CLSIZE;
                                splx(sk);
                                if (type != CTEXT)
                                        cnt.v_zfod += CLSIZE;
                                splx(sk);
@@ -351,8 +366,7 @@ valid:
                        }
                        pgtrace(TR_EXFOD);
                        cnt.v_exfod += CLSIZE;
                        }
                        pgtrace(TR_EXFOD);
                        cnt.v_exfod += CLSIZE;
-               } else
-                       panic("pagein vread");
+               }
                /*
                 * Fill from inode.  Try to find adjacent
                 * pages to bring in also.
                /*
                 * Fill from inode.  Try to find adjacent
                 * pages to bring in also.
@@ -365,7 +379,7 @@ valid:
                 * cache, so we explicitly flush them out to disk
                 * so that the proper data will be paged in.
                 */
                 * cache, so we explicitly flush them out to disk
                 * so that the proper data will be paged in.
                 */
-               blkflush(dev, bn, (long)CLSIZE*NBPG);
+               blkflush(dev, bn, (long)klsize*CLSIZE*NBPG);
 #ifdef TRACE
                if (type != CTEXT)
                        trace(TR_XFODMISS, dev, bn);
 #ifdef TRACE
                if (type != CTEXT)
                        trace(TR_XFODMISS, dev, bn);
@@ -416,6 +430,13 @@ skipswap:
         */
        pte = vtopte(p, vsave);
        pte->pg_v = 1;
         */
        pte = vtopte(p, vsave);
        pte->pg_v = 1;
+#ifdef REFBIT
+       /*
+        * Start with the page used so that pageout doesn't free it 
+        * immediately.
+        */
+       pte->pg_u = 1;
+#endif
        distcl(pte);
        if (type == CTEXT) {
                if (swerror == 0) {
        distcl(pte);
        if (type == CTEXT) {
                if (swerror == 0) {
@@ -448,11 +469,21 @@ skipswap:
                    opte.pg_fod == 0) {
                        /*
                         * Throw pre-paged data/stack pages at the
                    opte.pg_fod == 0) {
                        /*
                         * Throw pre-paged data/stack pages at the
-                        * bottom of the free list.
+                        * bottom of the free list; leave pg_u clear.
                         */
                        p->p_rssize -= CLSIZE;
                        memfree(pte, CLSIZE, 0);
                }
                         */
                        p->p_rssize -= CLSIZE;
                        memfree(pte, CLSIZE, 0);
                }
+#ifdef REFBIT
+               /*
+                * Text pages paged-in and allocated during the kluster
+                * must be validated, as they are now in the resident set.
+                */
+               if (v != vsave && type == CTEXT) {
+                       pte->pg_v = 1;
+                       distpte(p->p_textp, (unsigned)vtotp(p, v), pte);
+               }
+#endif
                newptes(pte, v, CLSIZE);
                v += CLSIZE;
                pte += CLSIZE;
                newptes(pte, v, CLSIZE);
                v += CLSIZE;
                pte += CLSIZE;
@@ -513,6 +544,7 @@ dpageout(p, dp, n)
                c = &cmap[pgtocm(pte->pg_pfnum)];
                if (c->c_lock || c->c_free)
                        continue;
                c = &cmap[pgtocm(pte->pg_pfnum)];
                if (c->c_lock || c->c_free)
                        continue;
+               uncachecl(pte);
                if (pte->pg_v) {
                        pte->pg_v = 0;
                        if (anycl(pte, pg_m))
                if (pte->pg_v) {
                        pte->pg_v = 0;
                        if (anycl(pte, pg_m))
@@ -530,7 +562,7 @@ dpageout(p, dp, n)
                                &klsize, klout, (daddr_t)0);
                        /* THIS ASSUMES THAT p == u.u_procp */
                        daddr = vtod(p, v, &u.u_dmap, &u.u_smap);
                                &klsize, klout, (daddr_t)0);
                        /* THIS ASSUMES THAT p == u.u_procp */
                        daddr = vtod(p, v, &u.u_dmap, &u.u_smap);
-                       (void)swap(p, daddr, ptob(v), klsize * ctob(CLSIZE),
+                       (void) swap(p, daddr, ptob(v), klsize * ctob(CLSIZE),
                            B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
                } else {
                        if (c->c_gone == 0)
                            B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
                } else {
                        if (c->c_gone == 0)
@@ -723,6 +755,8 @@ loop:
                        count = 0;
                cnt.v_scan++;
                nscan++;
                        count = 0;
                cnt.v_scan++;
                nscan++;
+               if (++backhand >= maxhand)
+                       backhand = 0;
                if (++fronthand >= maxhand) {
                        fronthand = 0;
                        cnt.v_rev++;
                if (++fronthand >= maxhand) {
                        fronthand = 0;
                        cnt.v_rev++;
@@ -736,8 +770,6 @@ loop:
                        }
                        count++;
                }
                        }
                        count++;
                }
-               if (++backhand >= maxhand)
-                       backhand = 0;
        }
        goto loop;
 }
        }
        goto loop;
 }
@@ -801,19 +833,39 @@ top:
                }
                break;
        }
                }
                break;
        }
-
        if (pte->pg_pfnum != cmtopg(hand))
                panic("bad c_page");
        if (pte->pg_pfnum != cmtopg(hand))
                panic("bad c_page");
-
+#ifdef REFBIT
+       /*
+        * If any processes attached to the text page have used
+        * it, then mark this one used and on the following
+        * distpte, they will all be marked used.
+        */
+       if (c->c_type == CTEXT && tanyu(xp, vtotp(rp, v))) 
+               pte->pg_u = 1;
+       /*
+        * If page is referenced, clear its reference bit.
+        * If page is not referenced, clear valid bit
+        * and add it to the free list.
+        */
+       uncachecl(pte);
+       if (anycl(pte, pg_u))
+#else
        /*
         * If page is valid; make invalid but reclaimable.
         * If this pte is not valid, then it must be reclaimable
         * and we can add it to the free list.
         */
        /*
         * If page is valid; make invalid but reclaimable.
         * If this pte is not valid, then it must be reclaimable
         * and we can add it to the free list.
         */
-       if (pte->pg_v) {
+       if (pte->pg_v)
+#endif
+       {
                if (whichhand == BACK)
                if (whichhand == BACK)
-                       return(0);
+                       return (0);
+#ifdef REFBIT
+               pte->pg_u = 0;
+#else
                pte->pg_v = 0;
                pte->pg_v = 0;
+#endif
                if (anycl(pte, pg_m))
                        pte->pg_m = 1;
                distcl(pte);
                if (anycl(pte, pg_m))
                        pte->pg_m = 1;
                distcl(pte);
@@ -906,6 +958,9 @@ loop2:
                /*
                 * Now committed to pushing the page...
                 */
                /*
                 * Now committed to pushing the page...
                 */
+#ifdef REFBIT
+               pte->pg_v = 0;
+#endif
                pte->pg_m = 0;
                distcl(pte);
                if (c->c_type == CTEXT)  {
                pte->pg_m = 0;
                distcl(pte);
                if (c->c_type == CTEXT)  {
@@ -917,7 +972,7 @@ loop2:
                if (klsize == 0)
                        panic("pageout klsize");
                daddr = vtod(rp, v, &pushutl.u_dmap, &pushutl.u_smap);
                if (klsize == 0)
                        panic("pageout klsize");
                daddr = vtod(rp, v, &pushutl.u_dmap, &pushutl.u_smap);
-               (void)swap(rp, daddr, ptob(v), klsize * ctob(CLSIZE),
+               (void) swap(rp, daddr, ptob(v), klsize * ctob(CLSIZE),
                    B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
                /*
                 * The cleaning of this page will be
                    B_WRITE, B_DIRTY, swapdev, pte->pg_pfnum);
                /*
                 * The cleaning of this page will be
@@ -927,17 +982,21 @@ loop2:
                 * so no havoc can result.
                 */
                return (1);     /* well, it'll be free soon */
                 * so no havoc can result.
                 */
                return (1);     /* well, it'll be free soon */
-
        }
        /*
        }
        /*
+        * Propagate valid bit changes.
         * Decrement the resident set size of the current
         * text object/process, and put the page in the
         * Decrement the resident set size of the current
         * text object/process, and put the page in the
-        * free list. Note that we don't give memfree the
-        * pte as its argument, since we don't want to destroy
-        * the pte.  If it hasn't already been discarded
+        * free list.  Don't detach the page yet;
         * it may yet have a chance to be reclaimed from
         * the free list.
         */
         * it may yet have a chance to be reclaimed from
         * the free list.
         */
+#ifdef REFBIT
+       pte->pg_v = 0;
+       distcl(pte);
+       if (c->c_type == CTEXT)
+               distpte(xp, (unsigned)vtotp(rp, v), pte);
+#endif
        if (c->c_gone == 0)
                if (c->c_type == CTEXT)
                        xp->x_rssize -= CLSIZE;
        if (c->c_gone == 0)
                if (c->c_type == CTEXT)
                        xp->x_rssize -= CLSIZE;
@@ -1028,7 +1087,7 @@ cleanup()
                                        upte = sptopte(rp, c->c_page);
                                        break;
                                }
                                        upte = sptopte(rp, c->c_page);
                                        break;
                                }
-                               if (upte->pg_v) 
+                               if (upte->pg_v)
                                        goto skip;
                                if (c->c_type == CTEXT)
                                        xp->x_rssize -= CLSIZE;
                                        goto skip;
                                if (c->c_type == CTEXT)
                                        xp->x_rssize -= CLSIZE;
@@ -1206,6 +1265,7 @@ klok(pte, rw)
                c = &cmap[pgtocm(pte->pg_pfnum)];
                if (c->c_lock || c->c_intrans)
                        return (0);
                c = &cmap[pgtocm(pte->pg_pfnum)];
                if (c->c_lock || c->c_intrans)
                        return (0);
+               uncachecl(pte);
                if (!dirtycl(pte))
                        return (0);
                return (1);
                if (!dirtycl(pte))
                        return (0);
                return (1);
@@ -1224,8 +1284,8 @@ klok(pte, rw)
  * and given the availability of memory includes them.
  * It wants to page in a file system block if it can.
  */
  * and given the availability of memory includes them.
  * It wants to page in a file system block if it can.
  */
-int nofodklust;
-int fodklcnt[KLMAX];
+int    nofodklust = 0;
+int    fodklcnt[KLMAX];
 
 fodkluster(p, v0, pte0, pkl, dev, pbn)
        register struct proc *p;
 
 fodkluster(p, v0, pte0, pkl, dev, pbn)
        register struct proc *p;
@@ -1237,18 +1297,15 @@ fodkluster(p, v0, pte0, pkl, dev, pbn)
 {
        register struct pte *pte;
        register struct fpte *fpte;
 {
        register struct pte *pte;
        register struct fpte *fpte;
-       struct cmap *c;
        register daddr_t bn;
        daddr_t bnswap;
        unsigned v, vmin, vmax;
        register int klsize;
        int klback, type, i;
 
        register daddr_t bn;
        daddr_t bnswap;
        unsigned v, vmin, vmax;
        register int klsize;
        int klback, type, i;
 
-       if (nofodklust)
-               return (v0);
        fodklcnt[0]++;
        *pkl = 1;
        fodklcnt[0]++;
        *pkl = 1;
-       if (freemem < KLMAX)
+       if (freemem < KLMAX || nofodklust)
                return (v0);
        if (isatsv(p, v0)) {
                type = CTEXT;
                return (v0);
        if (isatsv(p, v0)) {
                type = CTEXT;
@@ -1263,9 +1320,9 @@ fodkluster(p, v0, pte0, pkl, dev, pbn)
        bn = *pbn;
        v = v0;
        for (klsize = 1; klsize < KLMAX; klsize++) {
        bn = *pbn;
        v = v0;
        for (klsize = 1; klsize < KLMAX; klsize++) {
-               v -= CLSIZE;
-               if (v < vmin)
+               if (v <= vmin)
                        break;
                        break;
+               v -= CLSIZE;
                fpte -= CLSIZE;
                if (fpte->pg_fod == 0)
                        break;
                fpte -= CLSIZE;
                if (fpte->pg_fod == 0)
                        break;
@@ -1280,9 +1337,7 @@ fodkluster(p, v0, pte0, pkl, dev, pbn)
                         * swap device block.
                         */
                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                         * swap device block.
                         */
                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
-                       c = mfind(swapdev, bnswap);
-                       if (c)
-                               munhash(swapdev, bnswap);
+                       munhash(swapdev, bnswap);
                }
        }
        klback = klsize - 1;
                }
        }
        klback = klsize - 1;
@@ -1307,9 +1362,7 @@ fodkluster(p, v0, pte0, pkl, dev, pbn)
                         * swap device block.
                         */
                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
                         * swap device block.
                         */
                        bnswap = vtod(p, v, &u.u_dmap, &u.u_smap);
-                       c = mfind(swapdev, bnswap);
-                       if (c)
-                               munhash(swapdev, bnswap);
+                       munhash(swapdev, bnswap);
                }
        }
        if (klsize == 1)
                }
        }
        if (klsize == 1)
@@ -1346,3 +1399,25 @@ fodkluster(p, v0, pte0, pkl, dev, pbn)
        }
        return (v0);
 }
        }
        return (v0);
 }
+
+#ifdef REFBIT
+/*
+ * Examine the reference bits in the pte's of all
+ * processes linked to a particular text segment. 
+ */
+tanyu(xp, tp)
+       struct text *xp;
+       register tp;
+{
+       register struct proc *p;
+       register struct pte *pte;
+
+       for (p = xp->x_caddr; p; p = p->p_xlink) {
+               pte = tptopte(p, tp);
+               uncache(pte);
+               if (anycl(pte, pg_u))
+                       return (1);
+       }
+       return (0);
+}
+#endif