speed-ups using the new constants
[unix-history] / usr / src / sys / vm / vm_meter.c
index addb677..b23e009 100644 (file)
@@ -1,4 +1,4 @@
-/*     vm_meter.c      4.5     81/04/17        */
+/*     vm_meter.c      4.18    83/01/08        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/text.h"
 #include "../h/vm.h"
 #include "../h/cmap.h"
 #include "../h/text.h"
 #include "../h/vm.h"
 #include "../h/cmap.h"
+#include "../h/kernel.h"
 
 
-int    maxpgio = MAXPGIO;
 int    maxslp = MAXSLP;
 int    maxslp = MAXSLP;
-int    minfree = MINFREE;
-int    desfree = DESFREE;
-int    lotsfree = 0;           /* set to LOTSFREE in main unless adbed */
 int    saferss = SAFERSS;
 int    saferss = SAFERSS;
-int    slowscan = SLOWSCAN;
-int    fastscan = FASTSCAN;
+
+/*
+ * The following parameters control operation of the page replacement
+ * algorithm.  They are initialized to 0, and then computed at boot time
+ * based on the size of the system.  If they are patched non-zero in
+ * a loaded vmunix they are left alone and may thus be changed per system
+ * using adb on the loaded system.
+ */
+int    maxpgio = 0;
+int    minfree = 0;
+int    desfree = 0;
+int    lotsfree = 0;
+int    slowscan = 0;
+int    fastscan = 0;
 int    klin = KLIN;
 int    klin = KLIN;
+int    klseql = KLSEQL;
+int    klsdist = KLSDIST;
+int    kltxt = KLTXT;
 int    klout = KLOUT;
 int    multprog = -1;          /* so we don't count process 2 */
 
 double avenrun[3];             /* load average, of runnable procs */
 
 int    klout = KLOUT;
 int    multprog = -1;          /* so we don't count process 2 */
 
 double avenrun[3];             /* load average, of runnable procs */
 
+/*
+ * Setup the paging constants for the clock algorithm.
+ * Called after the system is initialized and the amount of memory
+ * and number of paging devices is known.
+ */
+setupclock()
+{
+
+       /*
+        * Setup thresholds for paging:
+        *      lotsfree        is threshold where paging daemon turns on
+        *      desfree         is amount of memory desired free.  if less
+        *                      than this for extended period, do swapping
+        *      minfree         is minimal amount of free memory which is
+        *                      tolerable.
+        *
+        * Strategy of 4/22/81:
+        *      lotsfree is 1/4 of memory free.
+        *      desfree is 200k bytes, but at most 1/8 of memory
+        *      minfree is 64k bytes, but at most 1/2 of desfree
+        */
+       if (lotsfree == 0)
+               lotsfree = LOOPPAGES / 4;
+       if (desfree == 0) {
+               desfree = (200*1024) / NBPG;
+               if (desfree > LOOPPAGES / 8)
+                       desfree = LOOPPAGES / 8;
+       }
+       if (minfree == 0) {
+               minfree = (64*1024) / NBPG;
+               if (minfree > desfree/2)
+                       minfree = desfree / 2;
+       }
+
+       /*
+        * Maxpgio thresholds how much paging is acceptable.
+        * This figures that 2/3 busy on an arm is all that is
+        * tolerable for paging.  We assume one operation per disk rev.
+        */
+       if (maxpgio == 0)
+               maxpgio = (DISKRPM * 2) / 3;
+
+       /*
+        * Clock to scan using max of ~~10% of processor time for sampling,
+        *     this estimated to allow maximum of 200 samples per second.
+        * This yields a ``fastscan'' of roughly (with CLSIZE=2):
+        *      <=1m    2m      3m      4m      8m
+        *      5s      10s     15s     20s     40s
+        */
+       if (nswdev == 1 && physmem*NBPG > 2*1024*(1024-16))
+               printf("WARNING: should run interleaved swap with >= 2Mb\n");
+       if (fastscan == 0)
+               fastscan = (LOOPPAGES/CLSIZE) / 200;
+       if (fastscan < 5)
+               fastscan = 5;
+       if (nswdev >= 2)
+               maxpgio = (maxpgio * 3) / 2;
+
+       /*
+        * Set slow scan time to 1/2 the fast scan time.
+        */
+       if (slowscan == 0)
+               slowscan = 2 * fastscan;
+#ifdef notdef
+       printf("slowscan %d, fastscan %d, maxpgio %d\n",
+           slowscan, fastscan, maxpgio);
+       printf("lotsfree %d, desfree %d, minfree %d\n",
+           lotsfree, desfree, minfree);
+#endif
+}
+
 /*
  * The main loop of the scheduling (swapping) process.
  *
 /*
  * The main loop of the scheduling (swapping) process.
  *
@@ -71,21 +154,26 @@ sched()
        register struct bigp *bp, *nbp;
        int biggot, gives;
 
        register struct bigp *bp, *nbp;
        int biggot, gives;
 
-       /*
-        * Check if paging rate is too high, or average of
-        * free list very low and if so, adjust multiprogramming
-        * load by swapping someone out.
-        *
-        * Avoid glitches: don't hard swap the only process,
-        * and don't swap based on paging rate if there is a reasonable
-        * amount of free memory.
-        */
 loop:
        wantin = 0;
        deservin = 0;
        sleeper = 0;
        p = 0;
 loop:
        wantin = 0;
        deservin = 0;
        sleeper = 0;
        p = 0;
-       if (kmapwnt || (multprog > 1 && avefree < desfree &&
+       /*
+        * See if paging system is overloaded; if so swap someone out.
+        * Conditions for hard outswap are:
+        *      if need kernel map (mix it up).
+        * or
+        *      1. if there are at least 2 runnable processes (on the average)
+        * and  2. the paging rate is excessive or memory is now VERY low.
+        * and  3. the short (5-second) and longer (30-second) average
+        *         memory is less than desirable.
+        */
+       if (
+#ifdef NOPAGING
+           freemem == 0 ||
+#endif
+           kmapwnt || (avenrun[0] >= 2 && imax(avefree, avefree30) < desfree &&
            (rate.v_pgin + rate.v_pgout > maxpgio || avefree < minfree))) {
                desperate = 1;
                goto hardswap;
            (rate.v_pgin + rate.v_pgout > maxpgio || avefree < minfree))) {
                desperate = 1;
                goto hardswap;
@@ -100,7 +188,8 @@ loop:
 
        case SRUN:
                if ((rp->p_flag&SLOAD) == 0) {
 
        case SRUN:
                if ((rp->p_flag&SLOAD) == 0) {
-                       rppri = rp->p_time - rp->p_swrss / nz((maxpgio/2) * CLSIZE) +
+                       rppri = rp->p_time -
+                           rp->p_swrss / nz((maxpgio/2) * (klin * CLSIZE)) +
                            rp->p_slptime - (rp->p_nice-NZERO)*8;
                        if (rppri > outpri) {
                                if (rp->p_poip)
                            rp->p_slptime - (rp->p_nice-NZERO)*8;
                        if (rppri > outpri) {
                                if (rp->p_poip)
@@ -160,11 +249,16 @@ loop:
        divisor = 1;
        if (outpri > maxslp/2) {
                deservin = 1;
        divisor = 1;
        if (outpri > maxslp/2) {
                deservin = 1;
+#ifdef NOPAGING
+               divisor = 1;
+#else
                divisor = 2;
                divisor = 2;
+#endif
        }
        needs = p->p_swrss;
        if (p->p_textp && p->p_textp->x_ccount == 0)
                needs += p->p_textp->x_swrss;
        }
        needs = p->p_swrss;
        if (p->p_textp && p->p_textp->x_ccount == 0)
                needs += p->p_textp->x_swrss;
+       needs = imin(needs, lotsfree);
        if (freemem - deficit > needs / divisor) {
                deficit += needs;
                if (swapin(p))
        if (freemem - deficit > needs / divisor) {
                deficit += needs;
                if (swapin(p))
@@ -256,6 +350,7 @@ hardswap:
                        gives = p->p_rssize;
                        if (p->p_textp)
                                gives += p->p_textp->x_rssize / p->p_textp->x_ccount;
                        gives = p->p_rssize;
                        if (p->p_textp)
                                gives += p->p_textp->x_rssize / p->p_textp->x_ccount;
+                       gives = imin(gives, lotsfree);
                        deficit += gives;
                } else
                        gives = 0;      /* someone else taketh away */
                        deficit += gives;
                } else
                        gives = 0;      /* someone else taketh away */
@@ -278,8 +373,10 @@ vmmeter()
 {
        register unsigned *cp, *rp, *sp;
 
 {
        register unsigned *cp, *rp, *sp;
 
-       deficit -= imin(deficit, imax(deficit / 10, maxpgio / 2));
+       deficit -= imin(deficit,
+           imax(deficit / 10, ((klin * CLSIZE) / 2) * maxpgio / 2));
        ave(avefree, freemem, 5);
        ave(avefree, freemem, 5);
+       ave(avefree30, freemem, 30);
        /* v_pgin is maintained by clock.c */
        cp = &cnt.v_first; rp = &rate.v_first; sp = &sum.v_first;
        while (cp <= &cnt.v_last) {
        /* v_pgin is maintained by clock.c */
        cp = &cnt.v_first; rp = &rate.v_first; sp = &sum.v_first;
        while (cp <= &cnt.v_last) {
@@ -288,7 +385,7 @@ vmmeter()
                *cp = 0;
                rp++, cp++, sp++;
        }
                *cp = 0;
                rp++, cp++, sp++;
        }
-       if (time % 5 == 0) {
+       if (time.tv_sec % 5 == 0) {
                vmtotal();
                rate.v_swpin = cnt.v_swpin;
                sum.v_swpin += cnt.v_swpin;
                vmtotal();
                rate.v_swpin = cnt.v_swpin;
                sum.v_swpin += cnt.v_swpin;
@@ -305,32 +402,30 @@ vmmeter()
        }
 }
 
        }
 }
 
-vmpago()
+#define        RATETOSCHEDPAGING       4               /* hz that is */
+
+/*
+ * Schedule rate for paging.
+ * Rate is linear interpolation between
+ * slowscan with lotsfree and fastscan when out of memory.
+ */
+schedpaging()
 {
 {
-       register int vavail;
-       register int scanrate;
+       register int vavail, scanrate;
 
 
-       /*
-        * Compute new rate for clock; if
-        * nonzero, restart clock.
-        * Rate ranges linearly from one rev per
-        * slowscan seconds when there is lotsfree memory
-        * available to one rev per fastscan seconds when
-        * there is no memory available.
-        */
        nscan = desscan = 0;
        vavail = freemem - deficit;
        if (vavail < 0)
                vavail = 0;
        nscan = desscan = 0;
        vavail = freemem - deficit;
        if (vavail < 0)
                vavail = 0;
-       if (freemem >= lotsfree)
-               return;
-       scanrate = (slowscan * vavail + fastscan * (lotsfree - vavail)) / nz(lotsfree);
-       desscan = LOOPSIZ / nz(scanrate);
-       /*
-        * DIVIDE BY 4 TO ACCOUNT FOR RUNNING 4* A SECOND (see clock.c)
-        */
-       desscan /= 4;
-       wakeup((caddr_t)&proc[2]);
+       if (freemem < lotsfree) {
+               scanrate =
+                       (slowscan * vavail + fastscan * (lotsfree - vavail)) /
+                               nz(lotsfree);
+               desscan = ((LOOPPAGES / CLSIZE) / nz(scanrate)) /
+                               RATETOSCHEDPAGING;
+               wakeup((caddr_t)&proc[2]);
+       }
+       timeout(schedpaging, (caddr_t)0, hz / RATETOSCHEDPAGING);
 }
 
 vmtotal()
 }
 
 vmtotal()