1 /* $OpenBSD: uvm_meter.c,v 1.9 2001/01/29 02:07:46 niklas Exp $ */ 2 /* $NetBSD: uvm_meter.c,v 1.8 1999/03/25 18:48:53 mrg Exp $ */ 3 4 /* 5 * Copyright (c) 1997 Charles D. Cranor and Washington University. 6 * Copyright (c) 1982, 1986, 1989, 1993 7 * The Regents of the University of California. 8 * 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Charles D. Cranor, 22 * Washington University, and the University of California, Berkeley 23 * and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 41 * from: Id: uvm_meter.c,v 1.1.2.1 1997/08/14 19:10:35 chuck Exp 42 */ 43 44 #include <sys/param.h> 45 #include <sys/proc.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <vm/vm.h> 49 #include <sys/sysctl.h> 50 #include <sys/exec.h> 51 52 #ifdef UVM_SWAP_ENCRYPT 53 #include <uvm/uvm_swap.h> 54 #include <uvm/uvm_swap_encrypt.h> 55 #endif 56 57 /* 58 * maxslp: ???? XXXCDC 59 */ 60 61 int maxslp = MAXSLP; /* patchable ... */ 62 struct loadavg averunnable; /* decl. */ 63 64 /* 65 * constants for averages over 1, 5, and 15 minutes when sampling at 66 * 5 second intervals. 67 */ 68 69 static fixpt_t cexp[3] = { 70 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 71 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 72 0.9944598480048967 * FSCALE, /* exp(-1/180) */ 73 }; 74 75 /* 76 * prototypes 77 */ 78 79 static void uvm_loadav __P((struct loadavg *)); 80 81 /* 82 * uvm_meter: calculate load average and wake up the swapper (if needed) 83 */ 84 void 85 uvm_meter() 86 { 87 if ((time.tv_sec % 5) == 0) 88 uvm_loadav(&averunnable); 89 if (proc0.p_slptime > (maxslp / 2)) 90 wakeup((caddr_t)&proc0); 91 } 92 93 /* 94 * uvm_loadav: compute a tenex style load average of a quantity on 95 * 1, 5, and 15 minute internvals. 96 */ 97 static void 98 uvm_loadav(avg) 99 struct loadavg *avg; 100 { 101 int i, nrun; 102 struct proc *p; 103 104 for (nrun = 0, p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 105 switch (p->p_stat) { 106 case SSLEEP: 107 if (p->p_priority > PZERO || p->p_slptime > 1) 108 continue; 109 /* fall through */ 110 case SRUN: 111 case SIDL: 112 nrun++; 113 } 114 } 115 for (i = 0; i < 3; i++) 116 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + 117 nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; 118 } 119 120 /* 121 * uvm_sysctl: sysctl hook into UVM system. 122 */ 123 int 124 uvm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 125 int *name; 126 u_int namelen; 127 void *oldp; 128 size_t *oldlenp; 129 void *newp; 130 size_t newlen; 131 struct proc *p; 132 { 133 struct vmtotal vmtotals; 134 struct _ps_strings _ps = { PS_STRINGS }; 135 136 switch (name[0]) { 137 case VM_SWAPENCRYPT: 138 #ifdef UVM_SWAP_ENCRYPT 139 return (swap_encrypt_ctl(name + 1, namelen - 1, oldp, oldlenp, 140 newp, newlen, p)); 141 #else 142 return (EOPNOTSUPP); 143 #endif 144 default: 145 /* all sysctl names at this level are terminal */ 146 if (namelen != 1) 147 return (ENOTDIR); /* overloaded */ 148 break; 149 } 150 151 switch (name[0]) { 152 case VM_LOADAVG: 153 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 154 sizeof(averunnable))); 155 156 case VM_METER: 157 uvm_total(&vmtotals); 158 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 159 sizeof(vmtotals))); 160 161 case VM_UVMEXP: 162 return (sysctl_rdstruct(oldp, oldlenp, newp, &uvmexp, 163 sizeof(uvmexp))); 164 165 case VM_PSSTRINGS: 166 return (sysctl_rdstruct(oldp, oldlenp, newp, &_ps, 167 sizeof(_ps))); 168 default: 169 return (EOPNOTSUPP); 170 } 171 /* NOTREACHED */ 172 } 173 174 /* 175 * uvm_total: calculate the current state of the system. 176 */ 177 void 178 uvm_total(totalp) 179 struct vmtotal *totalp; 180 { 181 struct proc *p; 182 #if 0 183 vm_map_entry_t entry; 184 vm_map_t map; 185 int paging; 186 #endif 187 188 memset(totalp, 0, sizeof *totalp); 189 190 /* 191 * calculate process statistics 192 */ 193 194 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 195 if (p->p_flag & P_SYSTEM) 196 continue; 197 switch (p->p_stat) { 198 case 0: 199 continue; 200 201 case SSLEEP: 202 case SSTOP: 203 if (p->p_flag & P_INMEM) { 204 if (p->p_priority <= PZERO) 205 totalp->t_dw++; 206 else if (p->p_slptime < maxslp) 207 totalp->t_sl++; 208 } else if (p->p_slptime < maxslp) 209 totalp->t_sw++; 210 if (p->p_slptime >= maxslp) 211 continue; 212 break; 213 214 case SRUN: 215 case SIDL: 216 if (p->p_flag & P_INMEM) 217 totalp->t_rq++; 218 else 219 totalp->t_sw++; 220 if (p->p_stat == SIDL) 221 continue; 222 break; 223 } 224 /* 225 * note active objects 226 */ 227 #if 0 228 /* 229 * XXXCDC: BOGUS! rethink this. in the mean time 230 * don't do it. 231 */ 232 paging = 0; 233 vm_map_lock(map); 234 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 235 entry != &map->header; entry = entry->next) { 236 if (entry->is_a_map || entry->is_sub_map || 237 entry->object.uvm_obj == NULL) 238 continue; 239 /* XXX how to do this with uvm */ 240 } 241 vm_map_unlock(map); 242 if (paging) 243 totalp->t_pw++; 244 #endif 245 } 246 /* 247 * Calculate object memory usage statistics. 248 */ 249 totalp->t_free = uvmexp.free; 250 totalp->t_vm = uvmexp.npages - uvmexp.free + uvmexp.swpginuse; 251 totalp->t_avm = uvmexp.active + uvmexp.swpginuse; /* XXX */ 252 totalp->t_rm = uvmexp.npages - uvmexp.free; 253 totalp->t_arm = uvmexp.active; 254 totalp->t_vmshr = 0; /* XXX */ 255 totalp->t_avmshr = 0; /* XXX */ 256 totalp->t_rmshr = 0; /* XXX */ 257 totalp->t_armshr = 0; /* XXX */ 258 } 259