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.3 (Berkeley) 12/30/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_next) { 55 switch (p->p_stat) { 56 case SSLEEP: 57 if (p->p_priority > 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 } 69 70 /* 71 * Attributes associated with virtual memory. 72 */ 73 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 74 int *name; 75 u_int namelen; 76 void *oldp; 77 size_t *oldlenp; 78 void *newp; 79 size_t newlen; 80 struct proc *p; 81 { 82 struct vmtotal vmtotals; 83 84 /* all sysctl names at this level are terminal */ 85 if (namelen != 1) 86 return (ENOTDIR); /* overloaded */ 87 88 switch (name[0]) { 89 case VM_LOADAVG: 90 averunnable.fscale = FSCALE; 91 return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable, 92 sizeof(averunnable))); 93 case VM_METER: 94 vmtotal(&vmtotals); 95 return (sysctl_rdstruct(oldp, oldlenp, newp, &vmtotals, 96 sizeof(vmtotals))); 97 default: 98 return (EOPNOTSUPP); 99 } 100 /* NOTREACHED */ 101 } 102 103 /* 104 * Calculate the current state of the system. 105 * Done on demand from getkerninfo(). 106 */ 107 void 108 vmtotal(totalp) 109 register struct vmtotal *totalp; 110 { 111 register struct proc *p; 112 register vm_map_entry_t entry; 113 register vm_object_t object; 114 register vm_map_t map; 115 int paging; 116 117 bzero(totalp, sizeof *totalp); 118 /* 119 * Mark all objects as inactive. 120 */ 121 simple_lock(&vm_object_list_lock); 122 for (object = vm_object_list.tqh_first; 123 object != NULL; 124 object = object->object_list.tqe_next) 125 object->flags &= ~OBJ_ACTIVE; 126 simple_unlock(&vm_object_list_lock); 127 /* 128 * Calculate process statistics. 129 */ 130 for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { 131 if (p->p_flag & P_SYSTEM) 132 continue; 133 switch (p->p_stat) { 134 case 0: 135 continue; 136 137 case SSLEEP: 138 case SSTOP: 139 if (p->p_flag & P_INMEM) { 140 if (p->p_priority <= PZERO) 141 totalp->t_dw++; 142 else if (p->p_slptime < maxslp) 143 totalp->t_sl++; 144 } else if (p->p_slptime < maxslp) 145 totalp->t_sw++; 146 if (p->p_slptime >= maxslp) 147 continue; 148 break; 149 150 case SRUN: 151 case SIDL: 152 if (p->p_flag & P_INMEM) 153 totalp->t_rq++; 154 else 155 totalp->t_sw++; 156 if (p->p_stat == SIDL) 157 continue; 158 break; 159 } 160 /* 161 * Note active objects. 162 */ 163 paging = 0; 164 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 165 entry != &map->header; entry = entry->next) { 166 if (entry->is_a_map || entry->is_sub_map || 167 entry->object.vm_object == NULL) 168 continue; 169 entry->object.vm_object->flags |= OBJ_ACTIVE; 170 paging |= entry->object.vm_object->paging_in_progress; 171 } 172 if (paging) 173 totalp->t_pw++; 174 } 175 /* 176 * Calculate object memory usage statistics. 177 */ 178 simple_lock(&vm_object_list_lock); 179 for (object = vm_object_list.tqh_first; 180 object != NULL; 181 object = object->object_list.tqe_next) { 182 totalp->t_vm += num_pages(object->size); 183 totalp->t_rm += object->resident_page_count; 184 if (object->flags & OBJ_ACTIVE) { 185 totalp->t_avm += num_pages(object->size); 186 totalp->t_arm += object->resident_page_count; 187 } 188 if (object->ref_count > 1) { 189 /* shared object */ 190 totalp->t_vmshr += num_pages(object->size); 191 totalp->t_rmshr += object->resident_page_count; 192 if (object->flags & OBJ_ACTIVE) { 193 totalp->t_avmshr += num_pages(object->size); 194 totalp->t_armshr += object->resident_page_count; 195 } 196 } 197 } 198 totalp->t_free = cnt.v_free_count; 199 } 200