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.49 2008/06/04 12:45:28 ad 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.49 2008/06/04 12:45:28 ad 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         static int count;
   87 
   88         if (++count >= 5) {
   89                 count = 0;
   90                 uvm_loadav(&averunnable);
   91         }
   92         if (lwp0.l_slptime > (maxslp / 2))
   93                 uvm_kick_scheduler();
   94 }
   95 
   96 /*
   97  * uvm_loadav: compute a tenex style load average of a quantity on
   98  * 1, 5, and 15 minute intervals.
   99  */
  100 static void
  101 uvm_loadav(struct loadavg *avg)
  102 {
  103         int i, nrun;
  104         struct lwp *l;
  105 
  106         nrun = 0;
  107 
  108         mutex_enter(proc_lock);
  109         LIST_FOREACH(l, &alllwp, l_list) {
  110                 if ((l->l_flag & (LW_SINTR | LW_SYSTEM)) != 0)
  111                         continue;
  112                 switch (l->l_stat) {
  113                 case LSSLEEP:
  114                         if (l->l_slptime > 1)
  115                                 continue;
  116                 /* fall through */
  117                 case LSRUN:
  118                 case LSONPROC:
  119                 case LSIDL:
  120                         nrun++;
  121                 }
  122         }
  123         mutex_exit(proc_lock);
  124 
  125         for (i = 0; i < 3; i++)
  126                 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] +
  127                     nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT;
  128 }
  129 
  130 /*
  131  * sysctl helper routine for the vm.vmmeter node.
  132  */
  133 static int
  134 sysctl_vm_meter(SYSCTLFN_ARGS)
  135 {
  136         struct sysctlnode node;
  137         struct vmtotal vmtotals;
  138 
  139         node = *rnode;
  140         node.sysctl_data = &vmtotals;
  141         uvm_total(&vmtotals);
  142 
  143         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  144 }
  145 
  146 /*
  147  * sysctl helper routine for the vm.uvmexp node.
  148  */
  149 static int
  150 sysctl_vm_uvmexp(SYSCTLFN_ARGS)
  151 {
  152         struct sysctlnode node;
  153 
  154         node = *rnode;
  155         if (oldp)
  156                 node.sysctl_size = min(*oldlenp, node.sysctl_size);
  157 
  158         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  159 }
  160 
  161 static int
  162 sysctl_vm_uvmexp2(SYSCTLFN_ARGS)
  163 {
  164         struct sysctlnode node;
  165         struct uvmexp_sysctl u;
  166         int active, inactive;
  167 
  168         uvm_estimatepageable(&active, &inactive);
  169 
  170         memset(&u, 0, sizeof(u));
  171 
  172         /* Entries here are in order of uvmexp_sysctl, not uvmexp */
  173         u.pagesize = uvmexp.pagesize;
  174         u.pagemask = uvmexp.pagemask;
  175         u.pageshift = uvmexp.pageshift;
  176         u.npages = uvmexp.npages;
  177         u.free = uvmexp.free;
  178         u.active = active;
  179         u.inactive = inactive;
  180         u.paging = uvmexp.paging;
  181         u.wired = uvmexp.wired;
  182         u.zeropages = uvmexp.zeropages;
  183         u.reserve_pagedaemon = uvmexp.reserve_pagedaemon;
  184         u.reserve_kernel = uvmexp.reserve_kernel;
  185         u.freemin = uvmexp.freemin;
  186         u.freetarg = uvmexp.freetarg;
  187         u.inactarg = 0; /* unused */
  188         u.wiredmax = uvmexp.wiredmax;
  189         u.nswapdev = uvmexp.nswapdev;
  190         u.swpages = uvmexp.swpages;
  191         u.swpginuse = uvmexp.swpginuse;
  192         u.swpgonly = uvmexp.swpgonly;
  193         u.nswget = uvmexp.nswget;
  194         u.faults = uvmexp.faults;
  195         u.traps = uvmexp.traps;
  196         u.intrs = uvmexp.intrs;
  197         u.swtch = uvmexp.swtch;
  198         u.softs = uvmexp.softs;
  199         u.syscalls = uvmexp.syscalls;
  200         u.pageins = uvmexp.pageins;
  201         u.swapins = uvmexp.swapins;
  202         u.swapouts = uvmexp.swapouts;
  203         u.pgswapin = uvmexp.pgswapin;
  204         u.pgswapout = uvmexp.pgswapout;
  205         u.forks = uvmexp.forks;
  206         u.forks_ppwait = uvmexp.forks_ppwait;
  207         u.forks_sharevm = uvmexp.forks_sharevm;
  208         u.pga_zerohit = uvmexp.pga_zerohit;
  209         u.pga_zeromiss = uvmexp.pga_zeromiss;
  210         u.zeroaborts = uvmexp.zeroaborts;
  211         u.fltnoram = uvmexp.fltnoram;
  212         u.fltnoanon = uvmexp.fltnoanon;
  213         u.fltpgwait = uvmexp.fltpgwait;
  214         u.fltpgrele = uvmexp.fltpgrele;
  215         u.fltrelck = uvmexp.fltrelck;
  216         u.fltrelckok = uvmexp.fltrelckok;
  217         u.fltanget = uvmexp.fltanget;
  218         u.fltanretry = uvmexp.fltanretry;
  219         u.fltamcopy = uvmexp.fltamcopy;
  220         u.fltnamap = uvmexp.fltnamap;
  221         u.fltnomap = uvmexp.fltnomap;
  222         u.fltlget = uvmexp.fltlget;
  223         u.fltget = uvmexp.fltget;
  224         u.flt_anon = uvmexp.flt_anon;
  225         u.flt_acow = uvmexp.flt_acow;
  226         u.flt_obj = uvmexp.flt_obj;
  227         u.flt_prcopy = uvmexp.flt_prcopy;
  228         u.flt_przero = uvmexp.flt_przero;
  229         u.pdwoke = uvmexp.pdwoke;
  230         u.pdrevs = uvmexp.pdrevs;
  231         u.pdswout = uvmexp.pdswout;
  232         u.pdfreed = uvmexp.pdfreed;
  233         u.pdscans = uvmexp.pdscans;
  234         u.pdanscan = uvmexp.pdanscan;
  235         u.pdobscan = uvmexp.pdobscan;
  236         u.pdreact = uvmexp.pdreact;
  237         u.pdbusy = uvmexp.pdbusy;
  238         u.pdpageouts = uvmexp.pdpageouts;
  239         u.pdpending = uvmexp.pdpending;
  240         u.pddeact = uvmexp.pddeact;
  241         u.anonpages = uvmexp.anonpages;
  242         u.filepages = uvmexp.filepages;
  243         u.execpages = uvmexp.execpages;
  244         u.colorhit = uvmexp.colorhit;
  245         u.colormiss = uvmexp.colormiss;
  246         u.cpuhit = uvmexp.cpuhit;
  247         u.cpumiss = uvmexp.cpumiss;
  248 
  249         node = *rnode;
  250         node.sysctl_data = &u;
  251         node.sysctl_size = sizeof(u);
  252         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  253 }
  254 
  255 /*
  256  * sysctl helper routine for uvm_pctparam.
  257  */
  258 static int
  259 uvm_sysctlpctparam(SYSCTLFN_ARGS)
  260 {
  261         int t, error;
  262         struct sysctlnode node;
  263         struct uvm_pctparam *pct;
  264 
  265         pct = rnode->sysctl_data;
  266         t = pct->pct_pct;
  267 
  268         node = *rnode;
  269         node.sysctl_data = &t;
  270         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  271         if (error || newp == NULL)
  272                 return error;
  273 
  274         if (t < 0 || t > 100)
  275                 return EINVAL;
  276 
  277         error = uvm_pctparam_check(pct, t);
  278         if (error) {
  279                 return error;
  280         }
  281         uvm_pctparam_set(pct, t);
  282 
  283         return (0);
  284 }
  285 
  286 /*
  287  * uvm_sysctl: sysctl hook into UVM system.
  288  */
  289 SYSCTL_SETUP(sysctl_vm_setup, "sysctl vm subtree setup")
  290 {
  291 
  292         sysctl_createv(clog, 0, NULL, NULL,
  293                        CTLFLAG_PERMANENT,
  294                        CTLTYPE_NODE, "vm", NULL,
  295                        NULL, 0, NULL, 0,
  296                        CTL_VM, CTL_EOL);
  297         sysctl_createv(clog, 0, NULL, NULL,
  298                        CTLFLAG_PERMANENT,
  299                        CTLTYPE_STRUCT, "vmmeter",
  300                        SYSCTL_DESCR("Simple system-wide virtual memory "
  301                                     "statistics"),
  302                        sysctl_vm_meter, 0, NULL, sizeof(struct vmtotal),
  303                        CTL_VM, VM_METER, CTL_EOL);
  304         sysctl_createv(clog, 0, NULL, NULL,
  305                        CTLFLAG_PERMANENT,
  306                        CTLTYPE_STRUCT, "loadavg",
  307                        SYSCTL_DESCR("System load average history"),
  308                        NULL, 0, &averunnable, sizeof(averunnable),
  309                        CTL_VM, VM_LOADAVG, CTL_EOL);
  310         sysctl_createv(clog, 0, NULL, NULL,
  311                        CTLFLAG_PERMANENT,
  312                        CTLTYPE_STRUCT, "uvmexp",
  313                        SYSCTL_DESCR("Detailed system-wide virtual memory "
  314                                     "statistics"),
  315                        sysctl_vm_uvmexp, 0, &uvmexp, sizeof(uvmexp),
  316                        CTL_VM, VM_UVMEXP, CTL_EOL);
  317         sysctl_createv(clog, 0, NULL, NULL,
  318                        CTLFLAG_PERMANENT,
  319                        CTLTYPE_INT, "nkmempages",
  320                        SYSCTL_DESCR("Default number of pages in kmem_map"),
  321                        NULL, 0, &nkmempages, 0,
  322                        CTL_VM, VM_NKMEMPAGES, CTL_EOL);
  323         sysctl_createv(clog, 0, NULL, NULL,
  324                        CTLFLAG_PERMANENT,
  325                        CTLTYPE_STRUCT, "uvmexp2",
  326                        SYSCTL_DESCR("Detailed system-wide virtual memory "
  327                                     "statistics (MI)"),
  328                        sysctl_vm_uvmexp2, 0, NULL, 0,
  329                        CTL_VM, VM_UVMEXP2, CTL_EOL);
  330         sysctl_createv(clog, 0, NULL, NULL,
  331                        CTLFLAG_PERMANENT, CTLTYPE_INT, "maxslp",
  332                        SYSCTL_DESCR("Maximum process sleep time before being "
  333                                     "swapped"),
  334                        NULL, 0, &maxslp, 0,
  335                        CTL_VM, VM_MAXSLP, CTL_EOL);
  336         sysctl_createv(clog, 0, NULL, NULL,
  337                        CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
  338                        CTLTYPE_INT, "uspace",
  339                        SYSCTL_DESCR("Number of bytes allocated for a kernel "
  340                                     "stack"),
  341                        NULL, USPACE, NULL, 0,
  342                        CTL_VM, VM_USPACE, CTL_EOL);
  343         sysctl_createv(clog, 0, NULL, NULL,
  344                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
  345                        CTLTYPE_INT, "idlezero",
  346                        SYSCTL_DESCR("Whether try to zero pages in idle loop"),
  347                        NULL, 0, &vm_page_zero_enable, 0,
  348                        CTL_VM, CTL_CREATE, CTL_EOL);
  349 
  350         uvmpdpol_sysctlsetup();
  351 }
  352 
  353 /*
  354  * uvm_total: calculate the current state of the system.
  355  */
  356 static void
  357 uvm_total(struct vmtotal *totalp)
  358 {
  359         struct lwp *l;
  360 #if 0
  361         struct vm_map_entry *   entry;
  362         struct vm_map *map;
  363         int paging;
  364 #endif
  365         int active;
  366 
  367         memset(totalp, 0, sizeof *totalp);
  368 
  369         /*
  370          * calculate process statistics
  371          */
  372         mutex_enter(proc_lock);
  373         LIST_FOREACH(l, &alllwp, l_list) {
  374                 if (l->l_proc->p_flag & PK_SYSTEM)
  375                         continue;
  376                 switch (l->l_stat) {
  377                 case 0:
  378                         continue;
  379 
  380                 case LSSLEEP:
  381                 case LSSTOP:
  382                         if (l->l_flag & LW_INMEM) {
  383                                 if (lwp_eprio(l) <= PZERO)
  384                                         totalp->t_dw++;
  385                                 else if (l->l_slptime < maxslp)
  386                                         totalp->t_sl++;
  387                         } else if (l->l_slptime < maxslp)
  388                                 totalp->t_sw++;
  389                         if (l->l_slptime >= maxslp)
  390                                 continue;
  391                         break;
  392 
  393                 case LSRUN:
  394                 case LSONPROC:
  395                 case LSIDL:
  396                         if (l->l_flag & LW_INMEM)
  397                                 totalp->t_rq++;
  398                         else
  399                                 totalp->t_sw++;
  400                         if (l->l_stat == LSIDL)
  401                                 continue;
  402                         break;
  403                 }
  404                 /*
  405                  * note active objects
  406                  */
  407 #if 0
  408                 /*
  409                  * XXXCDC: BOGUS!  rethink this.  in the mean time
  410                  * don't do it.
  411                  */
  412                 paging = 0;
  413                 vm_map_lock(map);
  414                 for (map = &p->p_vmspace->vm_map, entry = map->header.next;
  415                     entry != &map->header; entry = entry->next) {
  416                         if (entry->is_a_map || entry->is_sub_map ||
  417                             entry->object.uvm_obj == NULL)
  418                                 continue;
  419                         /* XXX how to do this with uvm */
  420                 }
  421                 vm_map_unlock(map);
  422                 if (paging)
  423                         totalp->t_pw++;
  424 #endif
  425         }
  426         mutex_exit(proc_lock);
  427 
  428         /*
  429          * Calculate object memory usage statistics.
  430          */
  431         uvm_estimatepageable(&active, NULL);
  432         totalp->t_free = uvmexp.free;
  433         totalp->t_vm = uvmexp.npages - uvmexp.free + uvmexp.swpginuse;
  434         totalp->t_avm = active + uvmexp.swpginuse;      /* XXX */
  435         totalp->t_rm = uvmexp.npages - uvmexp.free;
  436         totalp->t_arm = active;
  437         totalp->t_vmshr = 0;            /* XXX */
  438         totalp->t_avmshr = 0;           /* XXX */
  439         totalp->t_rmshr = 0;            /* XXX */
  440         totalp->t_armshr = 0;           /* XXX */
  441 }
  442 
  443 void
  444 uvm_pctparam_set(struct uvm_pctparam *pct, int val)
  445 {
  446 
  447         pct->pct_pct = val;
  448         pct->pct_scaled = val * UVM_PCTPARAM_SCALE / 100;
  449 }
  450 
  451 int
  452 uvm_pctparam_get(struct uvm_pctparam *pct)
  453 {
  454 
  455         return pct->pct_pct;
  456 }
  457 
  458 int
  459 uvm_pctparam_check(struct uvm_pctparam *pct, int val)
  460 {
  461 
  462         if (pct->pct_check == NULL) {
  463                 return 0;
  464         }
  465         return (*pct->pct_check)(pct, val);
  466 }
  467 
  468 void
  469 uvm_pctparam_init(struct uvm_pctparam *pct, int val,
  470     int (*fn)(struct uvm_pctparam *, int))
  471 {
  472 
  473         pct->pct_check = fn;
  474         uvm_pctparam_set(pct, val);
  475 }
  476 
  477 int
  478 uvm_pctparam_createsysctlnode(struct uvm_pctparam *pct, const char *name,
  479     const char *desc)
  480 {
  481 
  482         return sysctl_createv(NULL, 0, NULL, NULL,
  483             CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
  484             CTLTYPE_INT, name, SYSCTL_DESCR(desc),
  485             uvm_sysctlpctparam, 0, pct, 0, CTL_VM, CTL_CREATE, CTL_EOL);
  486 }

Cache object: f4508f71552a5fad81d950e37d75a8e4


[ 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.