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.12 (Berkeley) 09/03/91 8 */ 9 10 #include "param.h" 11 #include "proc.h" 12 #include "systm.h" 13 #include "kernel.h" 14 #include "vm.h" 15 16 fixpt_t averunnable[3]; /* load average, of runnable procs */ 17 18 int maxslp = MAXSLP; 19 int saferss = SAFERSS; 20 21 22 vmmeter() 23 { 24 register unsigned *cp, *rp, *sp; 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 loadav(avg) 47 register fixpt_t *avg; 48 { 49 register int i, nrun; 50 register struct proc *p; 51 52 for (nrun = 0, p = allproc; p != NULL; p = p->p_nxt) { 53 switch (p->p_stat) { 54 case SSLEEP: 55 if (p->p_pri > PZERO || p->p_slptime != 0) 56 continue; 57 /* fall through */ 58 case SRUN: 59 case SIDL: 60 nrun++; 61 } 62 } 63 for (i = 0; i < 3; i++) 64 avg[i] = (cexp[i] * avg[i] + nrun * FSCALE * (FSCALE - cexp[i])) 65 >> FSHIFT; 66 #if defined(COMPAT_43) && (defined(vax) || defined(tahoe)) 67 for (i = 0; i < 3; i++) 68 avenrun[i] = (double) averunnable[i] / FSCALE; 69 #endif /* COMPAT_43 */ 70 } 71 72 /* 73 * Calculate and return vmtotals structure. 74 */ 75 kinfo_meter(op, where, acopysize, arg, aneeded) 76 int op; 77 caddr_t where; 78 int *acopysize, arg, *aneeded; 79 { 80 struct vmtotal vmtotals; 81 int error; 82 83 *aneeded = sizeof(struct vmtotal); 84 if (where == NULL) 85 return (0); 86 if (*acopysize < sizeof(struct vmtotal)) 87 return (EINVAL); 88 vmtotal(&vmtotals); 89 if (error = copyout((caddr_t)&vmtotals, where, sizeof(struct vmtotal))) 90 return (error); 91 *acopysize = sizeof(struct vmtotal); 92 return (0); 93 } 94 95 /* 96 * Calculate the current state of the system. 97 * Done on demand from getkerninfo(). 98 */ 99 vmtotal(totalp) 100 register struct vmtotal *totalp; 101 { 102 register struct proc *p; 103 register vm_map_entry_t entry; 104 register vm_object_t object; 105 register vm_map_t map; 106 int paging; 107 108 bzero(totalp, sizeof *totalp); 109 /* 110 * Mark all objects as inactive. 111 */ 112 simple_unlock(&vm_object_list_lock); 113 simple_lock(&vm_object_list_lock); 114 object = (vm_object_t) queue_first(&vm_object_list); 115 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 116 object->flags &= ~OBJ_ACTIVE; 117 object = (vm_object_t) queue_next(&object->object_list); 118 } 119 simple_unlock(&vm_object_list_lock); 120 /* 121 * Calculate process statistics. 122 */ 123 for (p = allproc; p != NULL; p = p->p_nxt) { 124 if (p->p_flag & SSYS) 125 continue; 126 switch (p->p_stat) { 127 case 0: 128 continue; 129 130 case SSLEEP: 131 case SSTOP: 132 if (p->p_flag & SLOAD) { 133 if (p->p_pri <= PZERO) 134 totalp->t_dw++; 135 else if (p->p_slptime < maxslp) 136 totalp->t_sl++; 137 } else if (p->p_slptime < maxslp) 138 totalp->t_sw++; 139 if (p->p_slptime >= maxslp) 140 continue; 141 break; 142 143 case SRUN: 144 case SIDL: 145 if (p->p_flag & SLOAD) 146 totalp->t_rq++; 147 else 148 totalp->t_sw++; 149 if (p->p_stat == SIDL) 150 continue; 151 break; 152 } 153 /* 154 * Note active objects. 155 */ 156 paging = 0; 157 for (map = &p->p_vmspace->vm_map, entry = map->header.next; 158 entry != &map->header; entry = entry->next) { 159 if (entry->is_a_map || entry->is_sub_map) 160 continue; 161 entry->object.vm_object->flags |= OBJ_ACTIVE; 162 paging |= entry->object.vm_object->paging_in_progress; 163 } 164 if (paging) 165 totalp->t_pw++; 166 } 167 /* 168 * Calculate object memory usage statistics. 169 */ 170 simple_lock(&vm_object_list_lock); 171 object = (vm_object_t) queue_first(&vm_object_list); 172 while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 173 totalp->t_vm += num_pages(object->size); 174 totalp->t_rm += object->resident_page_count; 175 if (object->flags & OBJ_ACTIVE) { 176 totalp->t_avm += num_pages(object->size); 177 totalp->t_arm += object->resident_page_count; 178 } 179 if (object->ref_count > 1) { 180 /* shared object */ 181 totalp->t_vmshr += num_pages(object->size); 182 totalp->t_rmshr += object->resident_page_count; 183 if (object->flags & OBJ_ACTIVE) { 184 totalp->t_avmshr += num_pages(object->size); 185 totalp->t_armshr += object->resident_page_count; 186 } 187 } 188 object = (vm_object_t) queue_next(&object->object_list); 189 } 190 totalp->t_free = cnt.v_free_count; 191 } 192