getkerninfo skipped defaults ``dupedkeyed'' behind the root node;
[unix-history] / usr / src / sys / vm / vm_meter.c
index 9c499c7..a134d36 100644 (file)
@@ -1,28 +1,54 @@
-/*     vm_meter.c      3.6     %G%     */
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)vm_meter.c  7.8 (Berkeley) %G%
+ */
 
 
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/seg.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/proc.h"
-#include "../h/text.h"
-#include "../h/vm.h"
-#include "../h/cmap.h"
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "proc.h"
+#include "text.h"
+#include "vm.h"
+#include "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 */
 
 int    klout = KLOUT;
 int    multprog = -1;          /* so we don't count process 2 */
 
-double avenrun[3];             /* load average, of runnable procs */
+fixpt_t        averunnable[3];         /* load average, of runnable procs */
 
 /*
  * The main loop of the scheduling (swapping) process.
 
 /*
  * The main loop of the scheduling (swapping) process.
@@ -71,22 +97,25 @@ 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:
 loop:
-       (void) spl6();
+       wantin = 0;
        deservin = 0;
        sleeper = 0;
        p = 0;
        deservin = 0;
        sleeper = 0;
        p = 0;
-       if (kmapwnt || (multprog > 1 && avefree < desfree &&
-           (rate.v_pgin + rate.v_pgout > maxpgio || avefree < minfree))) {
+       /*
+        * 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 (kmapwnt ||
+           (averunnable[0] >= 2 * FSCALE &&
+            imax(avefree, avefree30) < desfree &&
+            (rate.v_pgin + rate.v_pgout > maxpgio || avefree < minfree))) {
                desperate = 1;
                goto hardswap;
        }
                desperate = 1;
                goto hardswap;
        }
@@ -96,11 +125,12 @@ loop:
         * look for someone who deserves to be brought in.
         */
        outpri = -20000;
         * look for someone who deserves to be brought in.
         */
        outpri = -20000;
-       for (rp = &proc[0]; rp < &proc[NPROC]; rp++) switch(rp->p_stat) {
+       for (rp = allproc; rp != NULL; rp = rp->p_nxt) switch(rp->p_stat) {
 
        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)
@@ -121,26 +151,27 @@ loop:
                    swappable(rp)) {
                        /*
                         * Kick out deadwood.
                    swappable(rp)) {
                        /*
                         * Kick out deadwood.
-                        * FOLLOWING 3 LINES MUST BE AT spl6().
                         */
                        rp->p_flag &= ~SLOAD;
                         */
                        rp->p_flag &= ~SLOAD;
-                       if (rp->p_stat == SRUN)
-                               remrq(rp);
-                       (void) swapout(rp, rp->p_dsize, rp->p_ssize);
-                       goto loop;
+                       (void) swapout(rp, rp->p_dsize, rp->p_mmsize, rp->p_ssize);
                }
                continue;
        }
 
        /*
                }
                continue;
        }
 
        /*
-        * No one wants in, so nothing to do.
+        * If something came ready after we checked it,
+        * wantin will be set.  Otherwise,
+        * no one wants in, so nothing to do.
         */
        if (outpri == -20000) {
         */
        if (outpri == -20000) {
-               runout++;
-               sleep((caddr_t)&runout, PSWP);
+               (void) splhigh();
+               if (wantin == 0) {
+                       runout++;
+                       sleep((caddr_t)&runout, PSWP);
+               }
+               (void) spl0();
                goto loop;
        }
                goto loop;
        }
-       (void) spl0();
        /*
         * Decide how deserving this guy is.  If he is deserving
         * we will be willing to work harder to bring him in.
        /*
         * Decide how deserving this guy is.  If he is deserving
         * we will be willing to work harder to bring him in.
@@ -158,6 +189,7 @@ loop:
        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))
@@ -171,7 +203,6 @@ hardswap:
         * Select the nbig largest jobs, then the oldest of these
         * is ``most likely to get booted.''
         */
         * Select the nbig largest jobs, then the oldest of these
         * is ``most likely to get booted.''
         */
-       (void) spl6();
        inp = p;
        sleeper = 0;
        if (nbig > MAXNBIG)
        inp = p;
        sleeper = 0;
        if (nbig > MAXNBIG)
@@ -180,11 +211,9 @@ hardswap:
                nbig = 1;
        biggot = 0;
        bplist.bp_link = 0;
                nbig = 1;
        biggot = 0;
        bplist.bp_link = 0;
-       for (rp = &proc[0]; rp < &proc[NPROC]; rp++) {
+       for (rp = allproc; rp != NULL; rp = rp->p_nxt) {
                if (!swappable(rp))
                        continue;
                if (!swappable(rp))
                        continue;
-               if (rp->p_stat==SZOMB)
-                       continue;
                if (rp == inp)
                        continue;
                if (rp->p_textp && rp->p_textp->x_flag&XLOCK)
                if (rp == inp)
                        continue;
                if (rp->p_textp && rp->p_textp->x_flag&XLOCK)
@@ -236,9 +265,11 @@ hardswap:
         * we kick the poor luser out.
         */
        if (sleeper || desperate && p || deservin && inpri > maxslp) {
         * we kick the poor luser out.
         */
        if (sleeper || desperate && p || deservin && inpri > maxslp) {
+               (void) splhigh();
                p->p_flag &= ~SLOAD;
                if (p->p_stat == SRUN)
                        remrq(p);
                p->p_flag &= ~SLOAD;
                if (p->p_stat == SRUN)
                        remrq(p);
+               (void) spl0();
                if (desperate) {
                        /*
                         * Want to give this space to the rest of
                if (desperate) {
                        /*
                         * Want to give this space to the rest of
@@ -248,20 +279,23 @@ 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 */
-               if (swapout(p, p->p_dsize, p->p_ssize) == 0)
+               if (swapout(p, p->p_dsize, p->p_mmsize, p->p_ssize) == 0)
                        deficit -= imin(gives, deficit);
                        deficit -= imin(gives, deficit);
-               goto loop;
+               else
+                       goto loop;
        }
        /*
         * Want to swap someone in, but can't
         * so wait on runin.
         */
        }
        /*
         * Want to swap someone in, but can't
         * so wait on runin.
         */
-       (void) spl6();
+       (void) splhigh();
        runin++;
        sleep((caddr_t)&runin, PSWP);
        runin++;
        sleep((caddr_t)&runin, PSWP);
+       (void) spl0();
        goto loop;
 }
 
        goto loop;
 }
 
@@ -269,8 +303,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) {
@@ -279,7 +315,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;
@@ -296,32 +332,25 @@ vmmeter()
        }
 }
 
        }
 }
 
-vmpago()
+/*
+ * Schedule rate for paging.
+ * Rate is linear interpolation between
+ * slowscan with lotsfree and fastscan when out of memory.
+ */
+schedpaging()
 {
        register int vavail;
 {
        register int vavail;
-       register int 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) {
+               desscan = (slowscan * vavail + fastscan * (lotsfree - vavail)) /
+                       nz(lotsfree) / RATETOSCHEDPAGING;
+               wakeup((caddr_t)&proc[2]);
+       }
+       timeout(schedpaging, (caddr_t)0, hz / RATETOSCHEDPAGING);
 }
 
 vmtotal()
 }
 
 vmtotal()
@@ -334,8 +363,8 @@ vmtotal()
        total.t_avmtxt = 0;
        total.t_rmtxt = 0;
        total.t_armtxt = 0;
        total.t_avmtxt = 0;
        total.t_rmtxt = 0;
        total.t_armtxt = 0;
-       for (xp = &text[0]; xp < &text[NTEXT]; xp++)
-               if (xp->x_iptr) {
+       for (xp = text; xp < textNTEXT; xp++)
+               if (xp->x_vptr) {
                        total.t_vmtxt += xp->x_size;
                        total.t_rmtxt += xp->x_rssize;
                        for (p = xp->x_caddr; p; p = p->p_xlink)
                        total.t_vmtxt += xp->x_size;
                        total.t_rmtxt += xp->x_rssize;
                        for (p = xp->x_caddr; p; p = p->p_xlink)
@@ -365,18 +394,21 @@ next:
        total.t_pw = 0;
        total.t_sl = 0;
        total.t_sw = 0;
        total.t_pw = 0;
        total.t_sl = 0;
        total.t_sw = 0;
-       for (p = &proc[0]; p < &proc[NPROC]; p++) {
+       for (p = allproc; p != NULL; p = p->p_nxt) {
                if (p->p_flag & SSYS)
                        continue;
                if (p->p_stat) {
                if (p->p_flag & SSYS)
                        continue;
                if (p->p_stat) {
-                       total.t_vm += p->p_dsize + p->p_ssize;
-                       total.t_rm += p->p_rssize;
+                       if (p->p_stat != SZOMB) {
+                               total.t_vm += p->p_dsize + p->p_ssize;
+                               total.t_rm += p->p_rssize;
+                       }
                        switch (p->p_stat) {
 
                        case SSLEEP:
                        switch (p->p_stat) {
 
                        case SSLEEP:
-                       case SSTOP:
-                               if (p->p_pri <= PZERO)
+                               if (p->p_pri <= PZERO && p->p_slptime == 0)
                                        nrun++;
                                        nrun++;
+                               /* fall through */
+                       case SSTOP:
                                if (p->p_flag & SPAGE)
                                        total.t_pw++;
                                else if (p->p_flag & SLOAD) {
                                if (p->p_flag & SPAGE)
                                        total.t_pw++;
                                else if (p->p_flag & SLOAD) {
@@ -409,17 +441,17 @@ active:
        total.t_rm += total.t_rmtxt;
        total.t_arm += total.t_armtxt;
        total.t_free = avefree;
        total.t_rm += total.t_rmtxt;
        total.t_arm += total.t_armtxt;
        total.t_free = avefree;
-       loadav(avenrun, nrun);
+       loadav(averunnable, nrun);
 }
 
 /*
  * Constants for averages over 1, 5, and 15 minutes
  * when sampling at 5 second intervals.
  */
 }
 
 /*
  * Constants for averages over 1, 5, and 15 minutes
  * when sampling at 5 second intervals.
  */
-double cexp[3] = {
-       0.9200444146293232    /* exp(-1/12) */
-       0.9834714538216174    /* exp(-1/60) */
-       0.9944598480048967    /* exp(-1/180) */
+fixpt_t        cexp[3] = {
+       0.9200444146293232 * FSCALE,    /* exp(-1/12) */
+       0.9834714538216174 * FSCALE,    /* exp(-1/60) */
+       0.9944598480048967 * FSCALE,    /* exp(-1/180) */
 };
 
 /*
 };
 
 /*
@@ -427,11 +459,16 @@ double    cexp[3] = {
  * 1, 5 and 15 minute intervals.
  */
 loadav(avg, n)
  * 1, 5 and 15 minute intervals.
  */
 loadav(avg, n)
-       register double *avg;
+       register fixpt_t *avg;
        int n;
 {
        register int i;
 
        for (i = 0; i < 3; i++)
        int n;
 {
        register int i;
 
        for (i = 0; i < 3; i++)
-               avg[i] = cexp[i] * avg[i] + n * (1.0 - cexp[i]);
+               avg[i] = (cexp[i] * avg[i] + n * FSCALE * (FSCALE - cexp[i]))
+                        >> FSHIFT;
+#if defined(COMPAT_43) && (defined(vax) || defined(tahoe))
+       for (i = 0; i < 3; i++)
+               avenrun[i] = (double) averunnable[i] / FSCALE;
+#endif /* COMPAT_43 */
 }
 }