be prepared to handle VM_PAGER_ERROR
[unix-history] / usr / src / sys / vm / vm_meter.c
index e108abb..0179dec 100644 (file)
@@ -4,86 +4,30 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vm_meter.c  7.10 (Berkeley) %G%
+ *     @(#)vm_meter.c  7.17 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "user.h"
-#include "proc.h"
-#include "kernel.h"
-#include "machine/vmparam.h"
-#include "vmmeter.h"
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
 
 
-fixpt_t        averunnable[3];         /* load average, of runnable procs */
+#include <vm/vm.h>
+
+struct loadavg averunnable;            /* load average, of runnable procs */
 
 int    maxslp = MAXSLP;
 int    saferss = SAFERSS;
 
 
 int    maxslp = MAXSLP;
 int    saferss = SAFERSS;
 
-
+void
 vmmeter()
 {
        register unsigned *cp, *rp, *sp;
 
        if (time.tv_sec % 5 == 0)
 vmmeter()
 {
        register unsigned *cp, *rp, *sp;
 
        if (time.tv_sec % 5 == 0)
-               vmtotal();
-       if (proc[0].p_slptime > maxslp/2) {
-               runout = 0;
-               wakeup((caddr_t)&runout);
-       }
-}
-
-vmtotal()
-{
-       register struct proc *p;
-       int nrun = 0;
-
-       total.t_vm = 0;
-       total.t_avm = 0;
-       total.t_rm = 0;
-       total.t_arm = 0;
-       total.t_rq = 0;
-       total.t_dw = 0;
-       total.t_pw = 0;
-       total.t_sl = 0;
-       total.t_sw = 0;
-       for (p = allproc; p != NULL; p = p->p_nxt) {
-               if (p->p_flag & SSYS)
-                       continue;
-               if (p->p_stat) {
-                       switch (p->p_stat) {
-
-                       case SSLEEP:
-                               if (p->p_pri <= PZERO && p->p_slptime == 0)
-                                       nrun++;
-                               /* fall through */
-                       case SSTOP:
-                               if (p->p_flag & SPAGE)
-                                       total.t_pw++;
-                               else if (p->p_flag & SLOAD) {
-                                       if (p->p_pri <= PZERO)
-                                               total.t_dw++;
-                                       else if (p->p_slptime < maxslp)
-                                               total.t_sl++;
-                               } else if (p->p_slptime < maxslp)
-                                       total.t_sw++;
-                               if (p->p_slptime < maxslp)
-                                       goto active;
-                               break;
-
-                       case SRUN:
-                       case SIDL:
-                               nrun++;
-                               if (p->p_flag & SLOAD)
-                                       total.t_rq++;
-                               else
-                                       total.t_sw++;
-active:
-                               break;
-                       }
-               }
-       }
-       loadav(averunnable, nrun);
+               loadav(&averunnable);
+       if (proc0.p_slptime > maxslp/2)
+               wakeup((caddr_t)&proc0);
 }
 
 /*
 }
 
 /*
@@ -100,17 +44,185 @@ fixpt_t   cexp[3] = {
  * Compute a tenex style load average of a quantity on
  * 1, 5 and 15 minute intervals.
  */
  * Compute a tenex style load average of a quantity on
  * 1, 5 and 15 minute intervals.
  */
-loadav(avg, n)
-       register fixpt_t *avg;
-       int n;
+void
+loadav(avg)
+       register struct loadavg *avg;
 {
 {
-       register int i;
+       register int i, nrun;
+       register struct proc *p;
 
 
+       for (nrun = 0, p = (struct proc *)allproc; p != NULL; p = p->p_nxt) {
+               switch (p->p_stat) {
+               case SSLEEP:
+                       if (p->p_pri > PZERO || p->p_slptime != 0)
+                               continue;
+                       /* fall through */
+               case SRUN:
+               case SIDL:
+                       nrun++;
+               }
+       }
        for (i = 0; i < 3; i++)
        for (i = 0; i < 3; i++)
-               avg[i] = (cexp[i] * avg[i] + n * FSCALE * (FSCALE - cexp[i]))
-                        >> FSHIFT;
+               avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
+                       nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
 #if defined(COMPAT_43) && (defined(vax) || defined(tahoe))
        for (i = 0; i < 3; i++)
 #if defined(COMPAT_43) && (defined(vax) || defined(tahoe))
        for (i = 0; i < 3; i++)
-               avenrun[i] = (double) averunnable[i] / FSCALE;
+               avenrun[i] = (double) avg->ldavg[i] / FSCALE;
 #endif /* COMPAT_43 */
 }
 #endif /* COMPAT_43 */
 }
+
+/*
+ * Load average information
+ */
+/* ARGSUSED */
+int
+kinfo_loadavg(op, where, acopysize, arg, aneeded)
+       int op;
+       register char *where;
+       int *acopysize, arg, *aneeded;
+{
+       int buflen, error;
+
+       *aneeded = sizeof(averunnable);
+       if (where == NULL)
+               return (0);
+       /*
+        * Check for enough buffering.
+        */
+       buflen = *acopysize;
+       if (buflen < sizeof(averunnable)) {
+               *acopysize = 0;
+               return (0);
+       }
+       /*
+        * Copyout averunnable structure.
+        */
+       averunnable.fscale = FSCALE;
+       if (error = copyout((caddr_t)&averunnable, where, sizeof(averunnable)))
+               return (error);
+       *acopysize = sizeof(averunnable);
+       return (0);
+}
+
+/*
+ * Calculate and return vmtotals structure.
+ */
+int
+kinfo_meter(op, where, acopysize, arg, aneeded)
+       int op;
+       caddr_t where;
+       int *acopysize, arg, *aneeded;
+{
+       struct vmtotal vmtotals;
+       int error;
+
+       *aneeded = sizeof(struct vmtotal);
+       if (where == NULL)
+               return (0);
+       if (*acopysize < sizeof(struct vmtotal))
+               return (EINVAL);
+       vmtotal(&vmtotals);
+       if (error = copyout((caddr_t)&vmtotals, where, sizeof(struct vmtotal)))
+               return (error);
+       *acopysize = sizeof(struct vmtotal);
+       return (0);
+}
+
+/*
+ * Calculate the current state of the system.
+ * Done on demand from getkerninfo().
+ */
+void
+vmtotal(totalp)
+       register struct vmtotal *totalp;
+{
+       register struct proc *p;
+       register vm_map_entry_t entry;
+       register vm_object_t object;
+       register vm_map_t map;
+       int paging;
+
+       bzero(totalp, sizeof *totalp);
+       /*
+        * Mark all objects as inactive.
+        */
+       simple_lock(&vm_object_list_lock);
+       object = (vm_object_t) queue_first(&vm_object_list);
+       while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
+               object->flags &= ~OBJ_ACTIVE;
+               object = (vm_object_t) queue_next(&object->object_list);
+       }
+       simple_unlock(&vm_object_list_lock);
+       /*
+        * Calculate process statistics.
+        */
+       for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) {
+               if (p->p_flag & SSYS)
+                       continue;
+               switch (p->p_stat) {
+               case 0:
+                       continue;
+
+               case SSLEEP:
+               case SSTOP:
+                       if (p->p_flag & SLOAD) {
+                               if (p->p_pri <= PZERO)
+                                       totalp->t_dw++;
+                               else if (p->p_slptime < maxslp)
+                                       totalp->t_sl++;
+                       } else if (p->p_slptime < maxslp)
+                               totalp->t_sw++;
+                       if (p->p_slptime >= maxslp)
+                               continue;
+                       break;
+
+               case SRUN:
+               case SIDL:
+                       if (p->p_flag & SLOAD)
+                               totalp->t_rq++;
+                       else
+                               totalp->t_sw++;
+                       if (p->p_stat == SIDL)
+                               continue;
+                       break;
+               }
+               /*
+                * Note active objects.
+                */
+               paging = 0;
+               for (map = &p->p_vmspace->vm_map, entry = map->header.next;
+                    entry != &map->header; entry = entry->next) {
+                       if (entry->is_a_map || entry->is_sub_map ||
+                           entry->object.vm_object == NULL)
+                               continue;
+                       entry->object.vm_object->flags |= OBJ_ACTIVE;
+                       paging |= entry->object.vm_object->paging_in_progress;
+               }
+               if (paging)
+                       totalp->t_pw++;
+       }
+       /*
+        * Calculate object memory usage statistics.
+        */
+       simple_lock(&vm_object_list_lock);
+       object = (vm_object_t) queue_first(&vm_object_list);
+       while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
+               totalp->t_vm += num_pages(object->size);
+               totalp->t_rm += object->resident_page_count;
+               if (object->flags & OBJ_ACTIVE) {
+                       totalp->t_avm += num_pages(object->size);
+                       totalp->t_arm += object->resident_page_count;
+               }
+               if (object->ref_count > 1) {
+                       /* shared object */
+                       totalp->t_vmshr += num_pages(object->size);
+                       totalp->t_rmshr += object->resident_page_count;
+                       if (object->flags & OBJ_ACTIVE) {
+                               totalp->t_avmshr += num_pages(object->size);
+                               totalp->t_armshr += object->resident_page_count;
+                       }
+               }
+               object = (vm_object_t) queue_next(&object->object_list);
+       }
+       totalp->t_free = cnt.v_free_count;
+}