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