1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vm_meter.c 8.7 (Berkeley) 05/10/95 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 26 if (time.tv_sec % 5 == 0) 27 loadav(&averunnable); 28 if (proc0.p_slptime > maxslp/2) 29 wakeup((caddr_t)&proc0); 30 } 31 32 /* 33 * Constants for averages over 1, 5, and 15 minutes 34 * when sampling at 5 second intervals. 35 */ 36 fixpt_t cexp[3] = { 37 0.9200444146293232 * FSCALE, /* exp(-1/12) */ 38 0.9834714538216174 * FSCALE, /* exp(-1/60) */ 39 0.9944598480048967 * FSCALE, /* exp(-1/180) */ 40 }; 41 42 /* 43 * Compute a tenex style load average of a quantity on 44 * 1, 5 and 15 minute intervals. 45 */ 46 void 47 loadav(avg) 48 register struct loadavg *avg; 49 { 50 register int i, nrun; 51 register struct proc *p; 52 53 for (nrun = 0, p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 54 switch (p->p_stat) { 55 case SSLEEP: 56 if (p->p_priority > PZERO || p->p_slptime != 0) 57 continue; 58 /* fall through */ 59 case SRUN: 60 case SIDL: 61 nrun++; 62 } 63 } 64 for (i = 0; i < 3; i++) 65 avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + 66 nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; 67 } 68 69 /* 70 * Attributes associated with virtual memory. 71 */ 72 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 73 int *name; 74 u_int namelen; 75 void *oldp; 76 size_t *oldlenp; 77 void *newp; 78 size_t newlen; 79 struct proc *p; 80 { 81 struct vmtotal vmtotals; 82 83 /* all sysctl names at this level are terminal */ 84 if (namelen != 1) 85 return (ENOTDIR); /* overloaded */ 86 87 switch (name[0]) { 88 case VM_LOADAVG: 89 averunnable.fscale = FSCALE; 90 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 91 sizeof(averunnable))); 92 case VM_METER: 93 vmtotal(&vmtotals); 94 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 95 sizeof(vmtotals))); 96 default: 97 return (EOPNOTSUPP); 98 } 99 /* NOTREACHED */ 100 } 101 102 /* 103 * Calculate the current state of the system. 104 * Done on demand from getkerninfo(). 105 */ 106 void 107 vmtotal(totalp) 108 register struct vmtotal *totalp; 109 { 110 register struct proc *p; 111 register vm_map_entry_t entry; 112 register vm_object_t object; 113 register vm_map_t map; 114 int paging; 115 116 bzero(totalp, sizeof *totalp); 117 /* 118 * Mark all objects as inactive. 119 */ 120 simple_lock(&vm_object_list_lock); 121 for (object = vm_object_list.tqh_first; 122 object != NULL; 123 object = object->object_list.tqe_next) 124 object->flags &= ~OBJ_ACTIVE; 125 simple_unlock(&vm_object_list_lock); 126 /* 127 * Calculate process statistics. 128 */ 129 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 130 if (p->p_flag & P_SYSTEM) 131 continue; 132 switch (p->p_stat) { 133 case 0: 134 continue; 135 136 case SSLEEP: 137 case SSTOP: 138 if (p->p_flag & P_INMEM) { 139 if (p->p_priority <= PZERO) 140 totalp->t_dw++; 141 else if (p->p_slptime < maxslp) 142 totalp->t_sl++; 143 } else if (p->p_slptime < maxslp) 144 totalp->t_sw++; 145 if (p->p_slptime >= maxslp) 146 continue; 147 break; 148 149 case SRUN: 150 case SIDL: 151 if (p->p_flag & P_INMEM) 152 totalp->t_rq++; 153 else 154 totalp->t_sw++; 155 if (p->p_stat == SIDL) 156 continue; 157 break; 158 } 159 /* 160 * Note active objects. 161 * 162 * XXX don't count shadow objects with no resident pages. 163 * This eliminates the forced shadows caused by MAP_PRIVATE. 164 * Right now we require that such an object completely shadow 165 * the original, to catch just those cases. 166 */ 167 paging = 0; 168 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 169 entry != &map->header; entry = entry->next) { 170 if (entry->is_a_map || entry->is_sub_map || 171 (object = entry->object.vm_object) == NULL) 172 continue; 173 while (object->shadow && 174 object->resident_page_count == 0 && 175 object->shadow_offset == 0 && 176 object->size == object->shadow->size) 177 object = object->shadow; 178 object->flags |= OBJ_ACTIVE; 179 paging |= object->paging_in_progress; 180 } 181 if (paging) 182 totalp->t_pw++; 183 } 184 /* 185 * Calculate object memory usage statistics. 186 */ 187 simple_lock(&vm_object_list_lock); 188 for (object = vm_object_list.tqh_first; 189 object != NULL; 190 object = object->object_list.tqe_next) { 191 totalp->t_vm += num_pages(object->size); 192 totalp->t_rm += object->resident_page_count; 193 if (object->flags & OBJ_ACTIVE) { 194 totalp->t_avm += num_pages(object->size); 195 totalp->t_arm += object->resident_page_count; 196 } 197 if (object->ref_count > 1) { 198 /* shared object */ 199 totalp->t_vmshr += num_pages(object->size); 200 totalp->t_rmshr += object->resident_page_count; 201 if (object->flags & OBJ_ACTIVE) { 202 totalp->t_avmshr += num_pages(object->size); 203 totalp->t_armshr += object->resident_page_count; 204 } 205 } 206 } 207 simple_unlock(&vm_object_list_lock); 208 totalp->t_free = cnt.v_free_count; 209 } 210