1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 34 * $Id: vm_meter.c,v 1.5 1995/01/09 16:05:47 davidg Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/proc.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <vm/vm.h> 42 #include <sys/sysctl.h> 43 44 struct loadavg averunnable; /* load average, of runnable procs */ 45 46 int maxslp = MAXSLP; 47 48 void 49 vmmeter() 50 { 51 52 if (time.tv_sec % 5 == 0) 53 loadav(&averunnable); 54 if (proc0.p_slptime > maxslp / 2) 55 wakeup((caddr_t) &proc0); 56 } 57 58 /* 59 * Constants for averages over 1, 5, and 15 minutes 60 * when sampling at 5 second intervals. 61 */ 62 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 * Compute a tenex style load average of a quantity on 70 * 1, 5 and 15 minute intervals. 71 */ 72 void 73 loadav(avg) 74 register struct loadavg *avg; 75 { 76 register int i, nrun; 77 register struct proc *p; 78 79 for (nrun = 0, p = (struct proc *) allproc; p != NULL; p = p->p_next) { 80 switch (p->p_stat) { 81 case SSLEEP: 82 if (p->p_priority > PZERO || p->p_slptime != 0) 83 continue; 84 /* fall through */ 85 case SRUN: 86 case SIDL: 87 nrun++; 88 } 89 } 90 for (i = 0; i < 3; i++) 91 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + 92 nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; 93 } 94 95 /* 96 * Attributes associated with virtual memory. 97 */ 98 int 99 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 100 int *name; 101 u_int namelen; 102 void *oldp; 103 size_t *oldlenp; 104 void *newp; 105 size_t newlen; 106 struct proc *p; 107 { 108 struct vmtotal vmtotals; 109 110 /* all sysctl names at this level are terminal */ 111 if (namelen != 1) 112 return (ENOTDIR); /* overloaded */ 113 114 switch (name[0]) { 115 case VM_LOADAVG: 116 averunnable.fscale = FSCALE; 117 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 118 sizeof(averunnable))); 119 case VM_METER: 120 vmtotal(&vmtotals); 121 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 122 sizeof(vmtotals))); 123 case VM_V_FREE_MIN: 124 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_free_min)); 125 case VM_V_FREE_TARGET: 126 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_free_target)); 127 case VM_V_FREE_RESERVED: 128 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_free_reserved)); 129 case VM_V_INACTIVE_TARGET: 130 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_inactive_target)); 131 case VM_V_CACHE_MIN: 132 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_cache_min)); 133 case VM_V_CACHE_MAX: 134 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_cache_max)); 135 case VM_V_PAGEOUT_FREE_MIN: 136 return (sysctl_int(oldp, oldlenp, newp, newlen, &cnt.v_pageout_free_min)); 137 138 default: 139 return (EOPNOTSUPP); 140 } 141 /* NOTREACHED */ 142 } 143 144 /* 145 * Calculate the current state of the system. 146 * Done on demand from getkerninfo(). 147 */ 148 void 149 vmtotal(totalp) 150 register struct vmtotal *totalp; 151 { 152 register struct proc *p; 153 register vm_map_entry_t entry; 154 register vm_object_t object; 155 register vm_map_t map; 156 int paging; 157 158 bzero(totalp, sizeof *totalp); 159 /* 160 * Mark all objects as inactive. 161 */ 162 simple_lock(&vm_object_list_lock); 163 for (object = vm_object_list.tqh_first; 164 object != NULL; 165 object = object->object_list.tqe_next) 166 object->flags &= ~OBJ_ACTIVE; 167 simple_unlock(&vm_object_list_lock); 168 /* 169 * Calculate process statistics. 170 */ 171 for (p = (struct proc *) allproc; p != NULL; p = p->p_next) { 172 if (p->p_flag & P_SYSTEM) 173 continue; 174 switch (p->p_stat) { 175 case 0: 176 continue; 177 178 case SSLEEP: 179 case SSTOP: 180 if (p->p_flag & P_INMEM) { 181 if (p->p_priority <= PZERO) 182 totalp->t_dw++; 183 else if (p->p_slptime < maxslp) 184 totalp->t_sl++; 185 } else if (p->p_slptime < maxslp) 186 totalp->t_sw++; 187 if (p->p_slptime >= maxslp) 188 continue; 189 break; 190 191 case SRUN: 192 case SIDL: 193 if (p->p_flag & P_INMEM) 194 totalp->t_rq++; 195 else 196 totalp->t_sw++; 197 if (p->p_stat == SIDL) 198 continue; 199 break; 200 } 201 /* 202 * Note active objects. 203 */ 204 paging = 0; 205 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 206 entry != &map->header; entry = entry->next) { 207 if (entry->is_a_map || entry->is_sub_map || 208 entry->object.vm_object == NULL) 209 continue; 210 entry->object.vm_object->flags |= OBJ_ACTIVE; 211 paging |= entry->object.vm_object->paging_in_progress; 212 } 213 if (paging) 214 totalp->t_pw++; 215 } 216 /* 217 * Calculate object memory usage statistics. 218 */ 219 simple_lock(&vm_object_list_lock); 220 for (object = vm_object_list.tqh_first; 221 object != NULL; 222 object = object->object_list.tqe_next) { 223 totalp->t_vm += num_pages(object->size); 224 totalp->t_rm += object->resident_page_count; 225 if (object->flags & OBJ_ACTIVE) { 226 totalp->t_avm += num_pages(object->size); 227 totalp->t_arm += object->resident_page_count; 228 } 229 if (object->ref_count > 1) { 230 /* shared object */ 231 totalp->t_vmshr += num_pages(object->size); 232 totalp->t_rmshr += object->resident_page_count; 233 if (object->flags & OBJ_ACTIVE) { 234 totalp->t_avmshr += num_pages(object->size); 235 totalp->t_armshr += object->resident_page_count; 236 } 237 } 238 } 239 totalp->t_free = cnt.v_free_count + cnt.v_cache_count; 240 } 241