The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/uvm/uvm_meter.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uvm_meter.c,v 1.43.2.1 2007/10/12 22:36:07 riz Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1997 Charles D. Cranor and Washington University.
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.
    7  *
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by Charles D. Cranor,
   21  *      Washington University, and the University of California, Berkeley
   22  *      and its contributors.
   23  * 4. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      @(#)vm_meter.c  8.4 (Berkeley) 1/4/94
   40  * from: Id: uvm_meter.c,v 1.1.2.1 1997/08/14 19:10:35 chuck Exp
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __KERNEL_RCSID(0, "$NetBSD: uvm_meter.c,v 1.43.2.1 2007/10/12 22:36:07 riz Exp $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/proc.h>
   48 #include <sys/systm.h>
   49 #include <sys/kernel.h>
   50 #include <sys/sysctl.h>
   51 
   52 #include <uvm/uvm_extern.h>
   53 #include <uvm/uvm_pdpolicy.h>
   54 
   55 /*
   56  * maxslp: ???? XXXCDC
   57  */
   58 
   59 int maxslp = MAXSLP;    /* patchable ... */
   60 struct loadavg averunnable;
   61 
   62 /*
   63  * constants for averages over 1, 5, and 15 minutes when sampling at
   64  * 5 second intervals.
   65  */
   66 
   67 static const fixpt_t cexp[3] = {
   68         0.9200444146293232 * FSCALE,    /* exp(-1/12) */
   69         0.9834714538216174 * FSCALE,    /* exp(-1/60) */
   70         0.9944598480048967 * FSCALE,    /* exp(-1/180) */
   71 };
   72 
   73 /*
   74  * prototypes
   75  */
   76 
   77 static void uvm_loadav(struct loadavg *);
   78 static void uvm_total(struct vmtotal *);
   79 
   80 /*
   81  * uvm_meter: calculate load average and wake up the swapper (if needed)
   82  */
   83 void
   84 uvm_meter(void)
   85 {
   86         if ((time_second % 5) == 0)
   87                 uvm_loadav(&averunnable);
   88         if (lwp0.l_slptime > (maxslp / 2))
   89                 wakeup(&proc0);
   90 }
   91 
   92 /*
   93  * uvm_loadav: compute a tenex style load average of a quantity on
   94  * 1, 5, and 15 minute internvals.
   95  */
   96 static void
   97 uvm_loadav(struct loadavg *avg)
   98 {
   99         int i, nrun;
  100         struct lwp *l;
  101 
  102         proclist_lock_read();
  103         nrun = 0;
  104         LIST_FOREACH(l, &alllwp, l_list) {
  105                 if ((l->l_flag & L_SINTR) != 0)
  106                         continue;
  107                 if ((l->l_proc->p_flag & P_SYSTEM) != 0)
  108                         continue;
  109                 switch (l->l_stat) {
  110                 case LSSLEEP:
  111                         if (l->l_slptime > 1)
  112                                 continue;
  113                 /* fall through */
  114                 case LSRUN:
  115                 case LSONPROC:
  116                 case LSIDL:
  117                         nrun++;
  118                 }
  119         }
  120         proclist_unlock_read();
  121         for (i = 0; i < 3; i++)
  122                 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
  123                     nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
  124 }
  125 
  126 /*
  127  * sysctl helper routine for the vm.vmmeter node.
  128  */
  129 static int
  130 sysctl_vm_meter(SYSCTLFN_ARGS)
  131 {
  132         struct sysctlnode node;
  133         struct vmtotal vmtotals;
  134 
  135         node = *rnode;
  136         node.sysctl_data = &vmtotals;
  137         uvm_total(&vmtotals);
  138 
  139         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  140 }
  141 
  142 /*
  143  * sysctl helper routine for the vm.uvmexp node.
  144  */
  145 static int
  146 sysctl_vm_uvmexp(SYSCTLFN_ARGS)
  147 {
  148         struct sysctlnode node;
  149 
  150         node = *rnode;
  151         if (oldp)
  152                 node.sysctl_size = min(*oldlenp, node.sysctl_size);
  153 
  154         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  155 }
  156 
  157 static int
  158 sysctl_vm_uvmexp2(SYSCTLFN_ARGS)
  159 {
  160         struct sysctlnode node;
  161         struct uvmexp_sysctl u;
  162         int active, inactive;
  163 
  164         uvm_estimatepageable(&active, &inactive);
  165 
  166         memset(&u, 0, sizeof(u));
  167 
  168         /* Entries here are in order of uvmexp_sysctl, not uvmexp */
  169         u.pagesize = uvmexp.pagesize;
  170         u.pagemask = uvmexp.pagemask;
  171         u.pageshift = uvmexp.pageshift;
  172         u.npages = uvmexp.npages;
  173         u.free = uvmexp.free;
  174         u.active = active;
  175         u.inactive = inactive;
  176         u.paging = uvmexp.paging;
  177         u.wired = uvmexp.wired;
  178         u.zeropages = uvmexp.zeropages;
  179         u.reserve_pagedaemon = uvmexp.reserve_pagedaemon;
  180         u.reserve_kernel = uvmexp.reserve_kernel;
  181         u.freemin = uvmexp.freemin;
  182         u.freetarg = uvmexp.freetarg;
  183         u.inactarg = 0; /* unused */
  184         u.wiredmax = uvmexp.wiredmax;
  185         u.nswapdev = uvmexp.nswapdev;
  186         u.swpages = uvmexp.swpages;
  187         u.swpginuse = uvmexp.swpginuse;
  188         u.swpgonly = uvmexp.swpgonly;
  189         u.nswget = uvmexp.nswget;
  190         u.faults = uvmexp.faults;
  191         u.traps = uvmexp.traps;
  192         u.intrs = uvmexp.intrs;
  193         u.swtch = uvmexp.swtch;
  194         u.softs = uvmexp.softs;
  195         u.syscalls = uvmexp.syscalls;
  196         u.pageins = uvmexp.pageins;
  197         u.swapins = uvmexp.swapins;
  198         u.swapouts = uvmexp.swapouts;
  199         u.pgswapin = uvmexp.pgswapin;
  200         u.pgswapout = uvmexp.pgswapout;
  201         u.forks = uvmexp.forks;
  202         u.forks_ppwait = uvmexp.forks_ppwait;
  203         u.forks_sharevm = uvmexp.forks_sharevm;
  204         u.pga_zerohit = uvmexp.pga_zerohit;
  205         u.pga_zeromiss = uvmexp.pga_zeromiss;
  206         u.zeroaborts = uvmexp.zeroaborts;
  207         u.fltnoram = uvmexp.fltnoram;
  208         u.fltnoanon = uvmexp.fltnoanon;
  209         u.fltpgwait = uvmexp.fltpgwait;
  210         u.fltpgrele = uvmexp.fltpgrele;
  211         u.fltrelck = uvmexp.fltrelck;
  212         u.fltrelckok = uvmexp.fltrelckok;
  213         u.fltanget = uvmexp.fltanget;
  214         u.fltanretry = uvmexp.fltanretry;
  215         u.fltamcopy = uvmexp.fltamcopy;
  216         u.fltnamap = uvmexp.fltnamap;
  217         u.fltnomap = uvmexp.fltnomap;
  218         u.fltlget = uvmexp.fltlget;
  219         u.fltget = uvmexp.fltget;
  220         u.flt_anon = uvmexp.flt_anon;
  221         u.flt_acow = uvmexp.flt_acow;
  222         u.flt_obj = uvmexp.flt_obj;
  223         u.flt_prcopy = uvmexp.flt_prcopy;
  224         u.flt_przero = uvmexp.flt_przero;
  225         u.pdwoke = uvmexp.pdwoke;
  226         u.pdrevs = uvmexp.pdrevs;
  227         u.pdswout = uvmexp.pdswout;
  228         u.pdfreed = uvmexp.pdfreed;
  229         u.pdscans = uvmexp.pdscans;
  230         u.pdanscan = uvmexp.pdanscan;
  231         u.pdobscan = uvmexp.pdobscan;
  232         u.pdreact = uvmexp.pdreact;
  233         u.pdbusy = uvmexp.pdbusy;
  234         u.pdpageouts = uvmexp.pdpageouts;
  235         u.pdpending = uvmexp.pdpending;
  236         u.pddeact = uvmexp.pddeact;
  237         u.anonpages = uvmexp.anonpages;
  238         u.filepages = uvmexp.filepages;
  239         u.execpages = uvmexp.execpages;
  240         u.colorhit = uvmexp.colorhit;
  241         u.colormiss = uvmexp.colormiss;
  242 
  243         node = *rnode;
  244         node.sysctl_data = &u;
  245         node.sysctl_size = sizeof(u);
  246         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  247 }
  248 
  249 /*
  250  * sysctl helper routine for uvm_pctparam.
  251  */
  252 static int
  253 uvm_sysctlpctparam(SYSCTLFN_ARGS)
  254 {
  255         int t, error;
  256         struct sysctlnode node;
  257         struct uvm_pctparam *pct;
  258 
  259         pct = rnode->sysctl_data;
  260         t = pct->pct_pct;
  261 
  262         node = *rnode;
  263         node.sysctl_data = &t;
  264         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  265         if (error || newp == NULL)
  266                 return error;
  267 
  268         if (t < 0 || t > 100)
  269                 return EINVAL;
  270 
  271         error = uvm_pctparam_check(pct, t);
  272         if (error) {
  273                 return error;
  274         }
  275         uvm_pctparam_set(pct, t);
  276 
  277         return (0);
  278 }
  279 
  280 /*
  281  * uvm_sysctl: sysctl hook into UVM system.
  282  */
  283 SYSCTL_SETUP(sysctl_vm_setup, "sysctl vm subtree setup")
  284 {
  285 
  286         sysctl_createv(clog, 0, NULL, NULL,
  287                        CTLFLAG_PERMANENT,
  288                        CTLTYPE_NODE, "vm", NULL,
  289                        NULL, 0, NULL, 0,
  290                        CTL_VM, CTL_EOL);
  291         sysctl_createv(clog, 0, NULL, NULL,
  292                        CTLFLAG_PERMANENT,
  293                        CTLTYPE_STRUCT, "vmmeter",
  294                        SYSCTL_DESCR("Simple system-wide virtual memory "
  295                                     "statistics"),
  296                        sysctl_vm_meter, 0, NULL, sizeof(struct vmtotal),
  297                        CTL_VM, VM_METER, CTL_EOL);
  298         sysctl_createv(clog, 0, NULL, NULL,
  299                        CTLFLAG_PERMANENT,
  300                        CTLTYPE_STRUCT, "loadavg",
  301                        SYSCTL_DESCR("System load average history"),
  302                        NULL, 0, &averunnable, sizeof(averunnable),
  303                        CTL_VM, VM_LOADAVG, CTL_EOL);
  304         sysctl_createv(clog, 0, NULL, NULL,
  305                        CTLFLAG_PERMANENT,
  306                        CTLTYPE_STRUCT, "uvmexp",
  307                        SYSCTL_DESCR("Detailed system-wide virtual memory "
  308                                     "statistics"),
  309                        sysctl_vm_uvmexp, 0, &uvmexp, sizeof(uvmexp),
  310                        CTL_VM, VM_UVMEXP, CTL_EOL);
  311         sysctl_createv(clog, 0, NULL, NULL,
  312                        CTLFLAG_PERMANENT,
  313                        CTLTYPE_INT, "nkmempages",
  314                        SYSCTL_DESCR("Default number of pages in kmem_map"),
  315                        NULL, 0, &nkmempages, 0,
  316                        CTL_VM, VM_NKMEMPAGES, CTL_EOL);
  317         sysctl_createv(clog, 0, NULL, NULL,
  318                        CTLFLAG_PERMANENT,
  319                        CTLTYPE_STRUCT, "uvmexp2",
  320                        SYSCTL_DESCR("Detailed system-wide virtual memory "
  321                                     "statistics (MI)"),
  322                        sysctl_vm_uvmexp2, 0, NULL, 0,
  323                        CTL_VM, VM_UVMEXP2, CTL_EOL);
  324         sysctl_createv(clog, 0, NULL, NULL,
  325                        CTLFLAG_PERMANENT, CTLTYPE_INT, "maxslp",
  326                        SYSCTL_DESCR("Maximum process sleep time before being "
  327                                     "swapped"),
  328                        NULL, 0, &maxslp, 0,
  329                        CTL_VM, VM_MAXSLP, CTL_EOL);
  330         sysctl_createv(clog, 0, NULL, NULL,
  331                        CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
  332                        CTLTYPE_INT, "uspace",
  333                        SYSCTL_DESCR("Number of bytes allocated for a kernel "
  334                                     "stack"),
  335                        NULL, USPACE, NULL, 0,
  336                        CTL_VM, VM_USPACE, CTL_EOL);
  337         sysctl_createv(clog, 0, NULL, NULL,
  338                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
  339                        CTLTYPE_INT, "idlezero",
  340                        SYSCTL_DESCR("Whether try to zero pages in idle loop"),
  341                        NULL, 0, &vm_page_zero_enable, 0,
  342                        CTL_VM, CTL_CREATE, CTL_EOL);
  343 
  344         uvmpdpol_sysctlsetup();
  345 }
  346 
  347 /*
  348  * uvm_total: calculate the current state of the system.
  349  */
  350 static void
  351 uvm_total(struct vmtotal *totalp)
  352 {
  353         struct lwp *l;
  354 #if 0
  355         struct vm_map_entry *   entry;
  356         struct vm_map *map;
  357         int paging;
  358 #endif
  359         int active;
  360 
  361         memset(totalp, 0, sizeof *totalp);
  362 
  363         /*
  364          * calculate process statistics
  365          */
  366 
  367         proclist_lock_read();
  368             LIST_FOREACH(l, &alllwp, l_list) {
  369                 if (l->l_proc->p_flag & P_SYSTEM)
  370                         continue;
  371                 switch (l->l_stat) {
  372                 case 0:
  373                         continue;
  374 
  375                 case LSSLEEP:
  376                 case LSSTOP:
  377                         if (l->l_flag & L_INMEM) {
  378                                 if (l->l_priority <= PZERO)
  379                                         totalp->t_dw++;
  380                                 else if (l->l_slptime < maxslp)
  381                                         totalp->t_sl++;
  382                         } else if (l->l_slptime < maxslp)
  383                                 totalp->t_sw++;
  384                         if (l->l_slptime >= maxslp)
  385                                 continue;
  386                         break;
  387 
  388                 case LSRUN:
  389                 case LSONPROC:
  390                 case LSIDL:
  391                         if (l->l_flag & L_INMEM)
  392                                 totalp->t_rq++;
  393                         else
  394                                 totalp->t_sw++;
  395                         if (l->l_stat == LSIDL)
  396                                 continue;
  397                         break;
  398                 }
  399                 /*
  400                  * note active objects
  401                  */
  402 #if 0
  403                 /*
  404                  * XXXCDC: BOGUS!  rethink this.  in the mean time
  405                  * don't do it.
  406                  */
  407                 paging = 0;
  408                 vm_map_lock(map);
  409                 for (map = &p->p_vmspace->vm_map, entry = map->header.next;
  410                     entry != &map->header; entry = entry->next) {
  411                         if (entry->is_a_map || entry->is_sub_map ||
  412                             entry->object.uvm_obj == NULL)
  413                                 continue;
  414                         /* XXX how to do this with uvm */
  415                 }
  416                 vm_map_unlock(map);
  417                 if (paging)
  418                         totalp->t_pw++;
  419 #endif
  420         }
  421         proclist_unlock_read();
  422         /*
  423          * Calculate object memory usage statistics.
  424          */
  425         uvm_estimatepageable(&active, NULL);
  426         totalp->t_free = uvmexp.free;
  427         totalp->t_vm = uvmexp.npages - uvmexp.free + uvmexp.swpginuse;
  428         totalp->t_avm = active + uvmexp.swpginuse;      /* XXX */
  429         totalp->t_rm = uvmexp.npages - uvmexp.free;
  430         totalp->t_arm = active;
  431         totalp->t_vmshr = 0;            /* XXX */
  432         totalp->t_avmshr = 0;           /* XXX */
  433         totalp->t_rmshr = 0;            /* XXX */
  434         totalp->t_armshr = 0;           /* XXX */
  435 }
  436 
  437 void
  438 uvm_pctparam_set(struct uvm_pctparam *pct, int val)
  439 {
  440 
  441         pct->pct_pct = val;
  442         pct->pct_scaled = val * UVM_PCTPARAM_SCALE / 100;
  443 }
  444 
  445 int
  446 uvm_pctparam_get(struct uvm_pctparam *pct)
  447 {
  448 
  449         return pct->pct_pct;
  450 }
  451 
  452 int
  453 uvm_pctparam_check(struct uvm_pctparam *pct, int val)
  454 {
  455 
  456         if (pct->pct_check == NULL) {
  457                 return 0;
  458         }
  459         return (*pct->pct_check)(pct, val);
  460 }
  461 
  462 void
  463 uvm_pctparam_init(struct uvm_pctparam *pct, int val,
  464     int (*fn)(struct uvm_pctparam *, int))
  465 {
  466 
  467         pct->pct_check = fn;
  468         uvm_pctparam_set(pct, val);
  469 }
  470 
  471 int
  472 uvm_pctparam_createsysctlnode(struct uvm_pctparam *pct, const char *name,
  473     const char *desc)
  474 {
  475 
  476         return sysctl_createv(NULL, 0, NULL, NULL,
  477             CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
  478             CTLTYPE_INT, name, SYSCTL_DESCR(desc),
  479             uvm_sysctlpctparam, 0, pct, 0, CTL_VM, CTL_CREATE, CTL_EOL);
  480 }

Cache object: b1f1f3bfa1f049ef407e964648457e05


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.