1 /* $NetBSD: uvm_meter.c,v 1.21 2001/07/14 06:36:03 matt 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/param.h> 44 #include <sys/proc.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <uvm/uvm_extern.h> 48 #include <sys/sysctl.h> 49 50 /* 51 * maxslp: ???? XXXCDC 52 */ 53 54 int maxslp = MAXSLP; /* patchable ... */ 55 struct loadavg averunnable; 56 57 /* 58 * constants for averages over 1, 5, and 15 minutes when sampling at 59 * 5 second intervals. 60 */ 61 62 static fixpt_t cexp[3] = { 63 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 64 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 65 0.9944598480048967 * FSCALE, /* exp(-1/180) */ 66 }; 67 68 /* 69 * prototypes 70 */ 71 72 static void uvm_loadav __P((struct loadavg *)); 73 static void uvm_total __P((struct vmtotal *)); 74 static int sysctl_uvmexp __P((void *, size_t *)); 75 76 /* 77 * uvm_meter: calculate load average and wake up the swapper (if needed) 78 */ 79 void 80 uvm_meter() 81 { 82 if ((time.tv_sec % 5) == 0) 83 uvm_loadav(&averunnable); 84 if (proc0.p_slptime > (maxslp / 2)) 85 wakeup(&proc0); 86 } 87 88 /* 89 * uvm_loadav: compute a tenex style load average of a quantity on 90 * 1, 5, and 15 minute internvals. 91 */ 92 static void 93 uvm_loadav(avg) 94 struct loadavg *avg; 95 { 96 int i, nrun; 97 struct proc *p; 98 99 proclist_lock_read(); 100 nrun = 0; 101 LIST_FOREACH(p, &allproc, p_list) { 102 switch (p->p_stat) { 103 case SSLEEP: 104 if (p->p_priority > PZERO || p->p_slptime > 1) 105 continue; 106 /* fall through */ 107 case SRUN: 108 case SONPROC: 109 case SIDL: 110 nrun++; 111 } 112 } 113 proclist_unlock_read(); 114 for (i = 0; i < 3; i++) 115 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + 116 nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; 117 } 118 119 /* 120 * uvm_sysctl: sysctl hook into UVM system. 121 */ 122 int 123 uvm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 124 int *name; 125 u_int namelen; 126 void *oldp; 127 size_t *oldlenp; 128 void *newp; 129 size_t newlen; 130 struct proc *p; 131 { 132 struct vmtotal vmtotals; 133 int rv, t; 134 135 /* all sysctl names at this level are terminal */ 136 if (namelen != 1) 137 return (ENOTDIR); /* overloaded */ 138 139 switch (name[0]) { 140 case VM_LOADAVG: 141 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 142 sizeof(averunnable))); 143 144 case VM_METER: 145 uvm_total(&vmtotals); 146 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 147 sizeof(vmtotals))); 148 149 case VM_UVMEXP: 150 return (sysctl_rdminstruct(oldp, oldlenp, newp, &uvmexp, 151 sizeof(uvmexp))); 152 case VM_UVMEXP2: 153 if (newp) 154 return (EPERM); 155 return (sysctl_uvmexp(oldp, oldlenp)); 156 157 case VM_NKMEMPAGES: 158 return (sysctl_rdint(oldp, oldlenp, newp, nkmempages)); 159 160 case VM_ANONMIN: 161 t = uvmexp.anonminpct; 162 rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); 163 if (rv) { 164 return rv; 165 } 166 if (t + uvmexp.vtextminpct + uvmexp.vnodeminpct > 95 || t < 0) { 167 return EINVAL; 168 } 169 uvmexp.anonminpct = t; 170 uvmexp.anonmin = t * 256 / 100; 171 return rv; 172 173 case VM_VTEXTMIN: 174 t = uvmexp.vtextminpct; 175 rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); 176 if (rv) { 177 return rv; 178 } 179 if (uvmexp.anonminpct + t + uvmexp.vnodeminpct > 95 || t < 0) { 180 return EINVAL; 181 } 182 uvmexp.vtextminpct = t; 183 uvmexp.vtextmin = t * 256 / 100; 184 return rv; 185 186 case VM_VNODEMIN: 187 t = uvmexp.vnodeminpct; 188 rv = sysctl_int(oldp, oldlenp, newp, newlen, &t); 189 if (rv) { 190 return rv; 191 } 192 if (uvmexp.anonminpct + uvmexp.vtextminpct + t > 95 || t < 0) { 193 return EINVAL; 194 } 195 uvmexp.vnodeminpct = t; 196 uvmexp.vnodemin = t * 256 / 100; 197 return rv; 198 199 case VM_MAXSLP: 200 return (sysctl_rdint(oldp, oldlenp, newp, maxslp)); 201 202 case VM_USPACE: 203 return (sysctl_rdint(oldp, oldlenp, newp, USPACE)); 204 205 default: 206 return (EOPNOTSUPP); 207 } 208 /* NOTREACHED */ 209 } 210 211 static int 212 sysctl_uvmexp(oldp, oldlenp) 213 void *oldp; 214 size_t *oldlenp; 215 { 216 struct uvmexp_sysctl u; 217 218 memset(&u, 0, sizeof(u)); 219 220 /* Entries here are in order of uvmexp_sysctl, not uvmexp */ 221 u.pagesize = uvmexp.pagesize; 222 u.pagemask = uvmexp.pagemask; 223 u.pageshift = uvmexp.pageshift; 224 u.npages = uvmexp.npages; 225 u.free = uvmexp.free; 226 u.active = uvmexp.active; 227 u.inactive = uvmexp.inactive; 228 u.paging = uvmexp.paging; 229 u.wired = uvmexp.wired; 230 u.zeropages = uvmexp.zeropages; 231 u.reserve_pagedaemon = uvmexp.reserve_pagedaemon; 232 u.reserve_kernel = uvmexp.reserve_kernel; 233 u.freemin = uvmexp.freemin; 234 u.freetarg = uvmexp.freetarg; 235 u.inactarg = uvmexp.inactarg; 236 u.wiredmax = uvmexp.wiredmax; 237 u.nswapdev = uvmexp.nswapdev; 238 u.swpages = uvmexp.swpages; 239 u.swpginuse = uvmexp.swpginuse; 240 u.swpgonly = uvmexp.swpgonly; 241 u.nswget = uvmexp.nswget; 242 u.nanon = uvmexp.nanon; 243 u.nanonneeded = uvmexp.nanonneeded; 244 u.nfreeanon = uvmexp.nfreeanon; 245 u.faults = uvmexp.faults; 246 u.traps = uvmexp.traps; 247 u.intrs = uvmexp.intrs; 248 u.swtch = uvmexp.swtch; 249 u.softs = uvmexp.softs; 250 u.syscalls = uvmexp.syscalls; 251 u.pageins = uvmexp.pageins; 252 u.swapins = uvmexp.swapins; 253 u.swapouts = uvmexp.swapouts; 254 u.pgswapin = uvmexp.pgswapin; 255 u.pgswapout = uvmexp.pgswapout; 256 u.forks = uvmexp.forks; 257 u.forks_ppwait = uvmexp.forks_ppwait; 258 u.forks_sharevm = uvmexp.forks_sharevm; 259 u.pga_zerohit = uvmexp.pga_zerohit; 260 u.pga_zeromiss = uvmexp.pga_zeromiss; 261 u.zeroaborts = uvmexp.zeroaborts; 262 u.fltnoram = uvmexp.fltnoram; 263 u.fltnoanon = uvmexp.fltnoanon; 264 u.fltpgwait = uvmexp.fltpgwait; 265 u.fltpgrele = uvmexp.fltpgrele; 266 u.fltrelck = uvmexp.fltrelck; 267 u.fltrelckok = uvmexp.fltrelckok; 268 u.fltanget = uvmexp.fltanget; 269 u.fltanretry = uvmexp.fltanretry; 270 u.fltamcopy = uvmexp.fltamcopy; 271 u.fltnamap = uvmexp.fltnamap; 272 u.fltnomap = uvmexp.fltnomap; 273 u.fltlget = uvmexp.fltlget; 274 u.fltget = uvmexp.fltget; 275 u.flt_anon = uvmexp.flt_anon; 276 u.flt_acow = uvmexp.flt_acow; 277 u.flt_obj = uvmexp.flt_obj; 278 u.flt_prcopy = uvmexp.flt_prcopy; 279 u.flt_przero = uvmexp.flt_przero; 280 u.pdwoke = uvmexp.pdwoke; 281 u.pdrevs = uvmexp.pdrevs; 282 u.pdswout = uvmexp.pdswout; 283 u.pdfreed = uvmexp.pdfreed; 284 u.pdscans = uvmexp.pdscans; 285 u.pdanscan = uvmexp.pdanscan; 286 u.pdobscan = uvmexp.pdobscan; 287 u.pdreact = uvmexp.pdreact; 288 u.pdbusy = uvmexp.pdbusy; 289 u.pdpageouts = uvmexp.pdpageouts; 290 u.pdpending = uvmexp.pdpending; 291 u.pddeact = uvmexp.pddeact; 292 u.anonpages = uvmexp.anonpages; 293 u.vnodepages = uvmexp.vnodepages; 294 u.vtextpages = uvmexp.vtextpages; 295 u.colorhit = uvmexp.colorhit; 296 u.colormiss = uvmexp.colormiss; 297 298 return (sysctl_rdminstruct(oldp, oldlenp, NULL, &u, sizeof(u))); 299 } 300 301 /* 302 * uvm_total: calculate the current state of the system. 303 */ 304 static void 305 uvm_total(totalp) 306 struct vmtotal *totalp; 307 { 308 struct proc *p; 309 #if 0 310 struct vm_map_entry * entry; 311 struct vm_map *map; 312 int paging; 313 #endif 314 315 memset(totalp, 0, sizeof *totalp); 316 317 /* 318 * calculate process statistics 319 */ 320 321 proclist_lock_read(); 322 LIST_FOREACH(p, &allproc, p_list) { 323 if (p->p_flag & P_SYSTEM) 324 continue; 325 switch (p->p_stat) { 326 case 0: 327 continue; 328 329 case SSLEEP: 330 case SSTOP: 331 if (p->p_flag & P_INMEM) { 332 if (p->p_priority <= PZERO) 333 totalp->t_dw++; 334 else if (p->p_slptime < maxslp) 335 totalp->t_sl++; 336 } else if (p->p_slptime < maxslp) 337 totalp->t_sw++; 338 if (p->p_slptime >= maxslp) 339 continue; 340 break; 341 342 case SRUN: 343 case SONPROC: 344 case SIDL: 345 if (p->p_flag & P_INMEM) 346 totalp->t_rq++; 347 else 348 totalp->t_sw++; 349 if (p->p_stat == SIDL) 350 continue; 351 break; 352 } 353 /* 354 * note active objects 355 */ 356 #if 0 357 /* 358 * XXXCDC: BOGUS! rethink this. in the mean time 359 * don't do it. 360 */ 361 paging = 0; 362 vm_map_lock(map); 363 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 364 entry != &map->header; entry = entry->next) { 365 if (entry->is_a_map || entry->is_sub_map || 366 entry->object.uvm_obj == NULL) 367 continue; 368 /* XXX how to do this with uvm */ 369 } 370 vm_map_unlock(map); 371 if (paging) 372 totalp->t_pw++; 373 #endif 374 } 375 proclist_unlock_read(); 376 /* 377 * Calculate object memory usage statistics. 378 */ 379 totalp->t_free = uvmexp.free; 380 totalp->t_vm = uvmexp.npages - uvmexp.free + uvmexp.swpginuse; 381 totalp->t_avm = uvmexp.active + uvmexp.swpginuse; /* XXX */ 382 totalp->t_rm = uvmexp.npages - uvmexp.free; 383 totalp->t_arm = uvmexp.active; 384 totalp->t_vmshr = 0; /* XXX */ 385 totalp->t_avmshr = 0; /* XXX */ 386 totalp->t_rmshr = 0; /* XXX */ 387 totalp->t_armshr = 0; /* XXX */ 388 } 389