Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
c4ec2128 KM |
2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
dbf0c423 | 5 | * %sccs.include.redist.c% |
c4ec2128 | 6 | * |
51cf4abc | 7 | * @(#)vm_meter.c 7.20 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
e3bf9f41 | 9 | |
3266719e KB |
10 | #include <sys/param.h> |
11 | #include <sys/proc.h> | |
12 | #include <sys/systm.h> | |
13 | #include <sys/kernel.h> | |
a76b2369 | 14 | #include <sys/sysctl.h> |
3266719e KB |
15 | |
16 | #include <vm/vm.h> | |
e3bf9f41 | 17 | |
8378439f | 18 | struct loadavg averunnable; /* load average, of runnable procs */ |
e3bf9f41 | 19 | |
f1f42678 KM |
20 | int maxslp = MAXSLP; |
21 | int saferss = SAFERSS; | |
e3bf9f41 | 22 | |
3266719e | 23 | void |
e3bf9f41 BJ |
24 | vmmeter() |
25 | { | |
26 | register unsigned *cp, *rp, *sp; | |
27 | ||
f1f42678 | 28 | if (time.tv_sec % 5 == 0) |
8378439f | 29 | loadav(&averunnable); |
ffe0d082 MK |
30 | if (proc0.p_slptime > maxslp/2) |
31 | wakeup((caddr_t)&proc0); | |
e3bf9f41 BJ |
32 | } |
33 | ||
e3bf9f41 BJ |
34 | /* |
35 | * Constants for averages over 1, 5, and 15 minutes | |
36 | * when sampling at 5 second intervals. | |
37 | */ | |
80b6b780 KM |
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) */ | |
e3bf9f41 BJ |
42 | }; |
43 | ||
44 | /* | |
45 | * Compute a tenex style load average of a quantity on | |
46 | * 1, 5 and 15 minute intervals. | |
47 | */ | |
3266719e | 48 | void |
2e9bff25 | 49 | loadav(avg) |
8378439f | 50 | register struct loadavg *avg; |
e3bf9f41 | 51 | { |
2e9bff25 KM |
52 | register int i, nrun; |
53 | register struct proc *p; | |
e3bf9f41 | 54 | |
60f392f2 | 55 | for (nrun = 0, p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { |
2e9bff25 KM |
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 | } | |
e3bf9f41 | 66 | for (i = 0; i < 3; i++) |
8378439f KM |
67 | avg->ldavg[i] = (cexp[i] * avg->ldavg[i] + |
68 | nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; | |
b3b807e5 | 69 | #if defined(COMPAT_43) && (defined(vax) || defined(tahoe)) |
80b6b780 | 70 | for (i = 0; i < 3; i++) |
8378439f | 71 | avenrun[i] = (double) avg->ldavg[i] / FSCALE; |
80b6b780 | 72 | #endif /* COMPAT_43 */ |
e3bf9f41 | 73 | } |
2e9bff25 | 74 | |
8378439f | 75 | /* |
a76b2369 | 76 | * Attributes associated with virtual memory. |
8378439f | 77 | */ |
04d563ec | 78 | vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) |
a76b2369 KM |
79 | int *name; |
80 | u_int namelen; | |
81 | void *oldp; | |
51cf4abc | 82 | size_t *oldlenp; |
a76b2369 | 83 | void *newp; |
51cf4abc | 84 | size_t newlen; |
04d563ec | 85 | struct proc *p; |
2e9bff25 KM |
86 | { |
87 | struct vmtotal vmtotals; | |
2e9bff25 | 88 | |
a76b2369 KM |
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 */ | |
2e9bff25 KM |
106 | } |
107 | ||
108 | /* | |
109 | * Calculate the current state of the system. | |
110 | * Done on demand from getkerninfo(). | |
111 | */ | |
3266719e | 112 | void |
2e9bff25 KM |
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 | */ | |
2e9bff25 KM |
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 | */ | |
60f392f2 | 136 | for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) { |
2e9bff25 KM |
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) { | |
31d5db89 MH |
172 | if (entry->is_a_map || entry->is_sub_map || |
173 | entry->object.vm_object == NULL) | |
2e9bff25 KM |
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 | } |