1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vm_meter.c 7.21 (Berkeley) 04/27/93 8 */ 9 10 #include <sys/param.h> 11 #include <sys/proc.h> 12 #include <sys/systm.h> 13 #include <sys/kernel.h> 14 #include <vm/vm.h> 15 #include <sys/sysctl.h> 16 17 struct loadavg averunnable; /* load average, of runnable procs */ 18 19 int maxslp = MAXSLP; 20 int saferss = SAFERSS; 21 22 void 23 vmmeter() 24 { 25 register unsigned *cp, *rp, *sp; 26 27 if (time.tv_sec % 5 == 0) 28 loadav(&averunnable); 29 if (proc0.p_slptime > maxslp/2) 30 wakeup((caddr_t)&proc0); 31 } 32 33 /* 34 * Constants for averages over 1, 5, and 15 minutes 35 * when sampling at 5 second intervals. 36 */ 37 fixpt_t cexp[3] = { 38 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 39 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 40 0.9944598480048967 * FSCALE, /* exp(-1/180) */ 41 }; 42 43 /* 44 * Compute a tenex style load average of a quantity on 45 * 1, 5 and 15 minute intervals. 46 */ 47 void 48 loadav(avg) 49 register struct loadavg *avg; 50 { 51 register int i, nrun; 52 register struct proc *p; 53 54 for (nrun = 0, p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 55 switch (p->p_stat) { 56 case SSLEEP: 57 if (p->p_pri > PZERO || p->p_slptime != 0) 58 continue; 59 /* fall through */ 60 case SRUN: 61 case SIDL: 62 nrun++; 63 } 64 } 65 for (i = 0; i < 3; i++) 66 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + 67 nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; 68 #if defined(COMPAT_43) && (defined(vax) || defined(tahoe)) 69 for (i = 0; i < 3; i++) 70 avenrun[i] = (double) avg->ldavg[i] / FSCALE; 71 #endif /* COMPAT_43 */ 72 } 73 74 /* 75 * Attributes associated with virtual memory. 76 */ 77 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 78 int *name; 79 u_int namelen; 80 void *oldp; 81 size_t *oldlenp; 82 void *newp; 83 size_t newlen; 84 struct proc *p; 85 { 86 struct vmtotal vmtotals; 87 88 /* all sysctl names at this level are terminal */ 89 if (namelen != 1) 90 return (ENOTDIR); /* overloaded */ 91 92 switch (name[0]) { 93 case VM_LOADAVG: 94 averunnable.fscale = FSCALE; 95 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 96 sizeof(averunnable))); 97 case VM_METER: 98 vmtotal(&vmtotals); 99 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 100 sizeof(vmtotals))); 101 default: 102 return (EOPNOTSUPP); 103 } 104 /* NOTREACHED */ 105 } 106 107 /* 108 * Calculate the current state of the system. 109 * Done on demand from getkerninfo(). 110 */ 111 void 112 vmtotal(totalp) 113 register struct vmtotal *totalp; 114 { 115 register struct proc *p; 116 register vm_map_entry_t entry; 117 register vm_object_t object; 118 register vm_map_t map; 119 int paging; 120 121 bzero(totalp, sizeof *totalp); 122 /* 123 * Mark all objects as inactive. 124 */ 125 simple_lock(&vm_object_list_lock); 126 object = (vm_object_t) queue_first(&vm_object_list); 127 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 128 object->flags &= ~OBJ_ACTIVE; 129 object = (vm_object_t) queue_next(&object->object_list); 130 } 131 simple_unlock(&vm_object_list_lock); 132 /* 133 * Calculate process statistics. 134 */ 135 for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 136 if (p->p_flag & SSYS) 137 continue; 138 switch (p->p_stat) { 139 case 0: 140 continue; 141 142 case SSLEEP: 143 case SSTOP: 144 if (p->p_flag & SLOAD) { 145 if (p->p_pri <= PZERO) 146 totalp->t_dw++; 147 else if (p->p_slptime < maxslp) 148 totalp->t_sl++; 149 } else if (p->p_slptime < maxslp) 150 totalp->t_sw++; 151 if (p->p_slptime >= maxslp) 152 continue; 153 break; 154 155 case SRUN: 156 case SIDL: 157 if (p->p_flag & SLOAD) 158 totalp->t_rq++; 159 else 160 totalp->t_sw++; 161 if (p->p_stat == SIDL) 162 continue; 163 break; 164 } 165 /* 166 * Note active objects. 167 */ 168 paging = 0; 169 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 170 entry != &map->header; entry = entry->next) { 171 if (entry->is_a_map || entry->is_sub_map || 172 entry->object.vm_object == NULL) 173 continue; 174 entry->object.vm_object->flags |= OBJ_ACTIVE; 175 paging |= entry->object.vm_object->paging_in_progress; 176 } 177 if (paging) 178 totalp->t_pw++; 179 } 180 /* 181 * Calculate object memory usage statistics. 182 */ 183 simple_lock(&vm_object_list_lock); 184 object = (vm_object_t) queue_first(&vm_object_list); 185 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 186 totalp->t_vm += num_pages(object->size); 187 totalp->t_rm += object->resident_page_count; 188 if (object->flags & OBJ_ACTIVE) { 189 totalp->t_avm += num_pages(object->size); 190 totalp->t_arm += object->resident_page_count; 191 } 192 if (object->ref_count > 1) { 193 /* shared object */ 194 totalp->t_vmshr += num_pages(object->size); 195 totalp->t_rmshr += object->resident_page_count; 196 if (object->flags & OBJ_ACTIVE) { 197 totalp->t_avmshr += num_pages(object->size); 198 totalp->t_armshr += object->resident_page_count; 199 } 200 } 201 object = (vm_object_t) queue_next(&object->object_list); 202 } 203 totalp->t_free = cnt.v_free_count; 204 } 205