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.1 (Berkeley) 06/11/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 } 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 object = (vm_object_t) queue_first(&vm_object_list); 123 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 124 object->flags &= ~OBJ_ACTIVE; 125 object = (vm_object_t) queue_next(&object->object_list); 126 } 127 simple_unlock(&vm_object_list_lock); 128 /* 129 * Calculate process statistics. 130 */ 131 for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { 132 if (p->p_flag & SSYS) 133 continue; 134 switch (p->p_stat) { 135 case 0: 136 continue; 137 138 case SSLEEP: 139 case SSTOP: 140 if (p->p_flag & SLOAD) { 141 if (p->p_pri <= PZERO) 142 totalp->t_dw++; 143 else if (p->p_slptime < maxslp) 144 totalp->t_sl++; 145 } else if (p->p_slptime < maxslp) 146 totalp->t_sw++; 147 if (p->p_slptime >= maxslp) 148 continue; 149 break; 150 151 case SRUN: 152 case SIDL: 153 if (p->p_flag & SLOAD) 154 totalp->t_rq++; 155 else 156 totalp->t_sw++; 157 if (p->p_stat == SIDL) 158 continue; 159 break; 160 } 161 /* 162 * Note active objects. 163 */ 164 paging = 0; 165 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 166 entry != &map->header; entry = entry->next) { 167 if (entry->is_a_map || entry->is_sub_map || 168 entry->object.vm_object == NULL) 169 continue; 170 entry->object.vm_object->flags |= OBJ_ACTIVE; 171 paging |= entry->object.vm_object->paging_in_progress; 172 } 173 if (paging) 174 totalp->t_pw++; 175 } 176 /* 177 * Calculate object memory usage statistics. 178 */ 179 simple_lock(&vm_object_list_lock); 180 object = (vm_object_t) queue_first(&vm_object_list); 181 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 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 object = (vm_object_t) queue_next(&object->object_list); 198 } 199 totalp->t_free = cnt.v_free_count; 200 } 201