1 /* $NetBSD: uvm_meter.c,v 1.49 2008/06/04 12:45:28 ad Exp $ */
4 * Copyright (c) 1997 Charles D. Cranor and Washington University.
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Charles D. Cranor,
21 * Washington University, and the University of California, Berkeley
22 * and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94
40 * from: Id: uvm_meter.c,v 1.1.2.1 1997/08/14 19:10:35 chuck Exp
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: uvm_meter.c,v 1.49 2008/06/04 12:45:28 ad Exp $");
46 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
52 #include <uvm/uvm_extern.h>
53 #include <uvm/uvm_pdpolicy.h>
59 int maxslp
= MAXSLP
; /* patchable ... */
60 struct loadavg averunnable
;
63 * constants for averages over 1, 5, and 15 minutes when sampling at
67 static const fixpt_t cexp
[3] = {
68 0.9200444146293232 * FSCALE
, /* exp(-1/12) */
69 0.9834714538216174 * FSCALE
, /* exp(-1/60) */
70 0.9944598480048967 * FSCALE
, /* exp(-1/180) */
77 static void uvm_loadav(struct loadavg
*);
78 static void uvm_total(struct vmtotal
*);
81 * uvm_meter: calculate load average.
90 uvm_loadav(&averunnable
);
95 * uvm_loadav: compute a tenex style load average of a quantity on
96 * 1, 5, and 15 minute intervals.
99 uvm_loadav(struct loadavg
*avg
)
106 mutex_enter(proc_lock
);
107 LIST_FOREACH(l
, &alllwp
, l_list
) {
108 if ((l
->l_flag
& (LW_SINTR
| LW_SYSTEM
)) != 0)
112 if (l
->l_slptime
> 1)
121 mutex_exit(proc_lock
);
123 for (i
= 0; i
< 3; i
++)
124 avg
->ldavg
[i
] = (cexp
[i
] * avg
->ldavg
[i
] +
125 nrun
* FSCALE
* (FSCALE
- cexp
[i
])) >> FSHIFT
;
129 * sysctl helper routine for the vm.vmmeter node.
132 sysctl_vm_meter(SYSCTLFN_ARGS
)
134 struct sysctlnode node
;
135 struct vmtotal vmtotals
;
138 node
.sysctl_data
= &vmtotals
;
139 uvm_total(&vmtotals
);
141 return (sysctl_lookup(SYSCTLFN_CALL(&node
)));
145 * sysctl helper routine for the vm.uvmexp node.
148 sysctl_vm_uvmexp(SYSCTLFN_ARGS
)
150 struct sysctlnode node
;
154 node
.sysctl_size
= min(*oldlenp
, node
.sysctl_size
);
156 return (sysctl_lookup(SYSCTLFN_CALL(&node
)));
160 sysctl_vm_uvmexp2(SYSCTLFN_ARGS
)
162 struct sysctlnode node
;
163 struct uvmexp_sysctl u
;
164 int active
, inactive
;
166 uvm_estimatepageable(&active
, &inactive
);
168 memset(&u
, 0, sizeof(u
));
170 /* Entries here are in order of uvmexp_sysctl, not uvmexp */
171 u
.pagesize
= uvmexp
.pagesize
;
172 u
.pagemask
= uvmexp
.pagemask
;
173 u
.pageshift
= uvmexp
.pageshift
;
174 u
.npages
= uvmexp
.npages
;
175 u
.free
= uvmexp
.free
;
177 u
.inactive
= inactive
;
178 u
.paging
= uvmexp
.paging
;
179 u
.wired
= uvmexp
.wired
;
180 u
.zeropages
= uvmexp
.zeropages
;
181 u
.reserve_pagedaemon
= uvmexp
.reserve_pagedaemon
;
182 u
.reserve_kernel
= uvmexp
.reserve_kernel
;
183 u
.freemin
= uvmexp
.freemin
;
184 u
.freetarg
= uvmexp
.freetarg
;
185 u
.inactarg
= 0; /* unused */
186 u
.wiredmax
= uvmexp
.wiredmax
;
187 u
.nswapdev
= uvmexp
.nswapdev
;
188 u
.swpages
= uvmexp
.swpages
;
189 u
.swpginuse
= uvmexp
.swpginuse
;
190 u
.swpgonly
= uvmexp
.swpgonly
;
191 u
.nswget
= uvmexp
.nswget
;
192 u
.faults
= uvmexp
.faults
;
193 u
.traps
= uvmexp
.traps
;
194 u
.intrs
= uvmexp
.intrs
;
195 u
.swtch
= uvmexp
.swtch
;
196 u
.softs
= uvmexp
.softs
;
197 u
.syscalls
= uvmexp
.syscalls
;
198 u
.pageins
= uvmexp
.pageins
;
199 u
.pgswapin
= uvmexp
.pgswapin
;
200 u
.pgswapout
= uvmexp
.pgswapout
;
201 u
.forks
= uvmexp
.forks
;
202 u
.forks_ppwait
= uvmexp
.forks_ppwait
;
203 u
.forks_sharevm
= uvmexp
.forks_sharevm
;
204 u
.pga_zerohit
= uvmexp
.pga_zerohit
;
205 u
.pga_zeromiss
= uvmexp
.pga_zeromiss
;
206 u
.zeroaborts
= uvmexp
.zeroaborts
;
207 u
.fltnoram
= uvmexp
.fltnoram
;
208 u
.fltnoanon
= uvmexp
.fltnoanon
;
209 u
.fltpgwait
= uvmexp
.fltpgwait
;
210 u
.fltpgrele
= uvmexp
.fltpgrele
;
211 u
.fltrelck
= uvmexp
.fltrelck
;
212 u
.fltrelckok
= uvmexp
.fltrelckok
;
213 u
.fltanget
= uvmexp
.fltanget
;
214 u
.fltanretry
= uvmexp
.fltanretry
;
215 u
.fltamcopy
= uvmexp
.fltamcopy
;
216 u
.fltnamap
= uvmexp
.fltnamap
;
217 u
.fltnomap
= uvmexp
.fltnomap
;
218 u
.fltlget
= uvmexp
.fltlget
;
219 u
.fltget
= uvmexp
.fltget
;
220 u
.flt_anon
= uvmexp
.flt_anon
;
221 u
.flt_acow
= uvmexp
.flt_acow
;
222 u
.flt_obj
= uvmexp
.flt_obj
;
223 u
.flt_prcopy
= uvmexp
.flt_prcopy
;
224 u
.flt_przero
= uvmexp
.flt_przero
;
225 u
.pdwoke
= uvmexp
.pdwoke
;
226 u
.pdrevs
= uvmexp
.pdrevs
;
227 u
.pdfreed
= uvmexp
.pdfreed
;
228 u
.pdscans
= uvmexp
.pdscans
;
229 u
.pdanscan
= uvmexp
.pdanscan
;
230 u
.pdobscan
= uvmexp
.pdobscan
;
231 u
.pdreact
= uvmexp
.pdreact
;
232 u
.pdbusy
= uvmexp
.pdbusy
;
233 u
.pdpageouts
= uvmexp
.pdpageouts
;
234 u
.pdpending
= uvmexp
.pdpending
;
235 u
.pddeact
= uvmexp
.pddeact
;
236 u
.anonpages
= uvmexp
.anonpages
;
237 u
.filepages
= uvmexp
.filepages
;
238 u
.execpages
= uvmexp
.execpages
;
239 u
.colorhit
= uvmexp
.colorhit
;
240 u
.colormiss
= uvmexp
.colormiss
;
241 u
.cpuhit
= uvmexp
.cpuhit
;
242 u
.cpumiss
= uvmexp
.cpumiss
;
245 node
.sysctl_data
= &u
;
246 node
.sysctl_size
= sizeof(u
);
247 return (sysctl_lookup(SYSCTLFN_CALL(&node
)));
251 * sysctl helper routine for uvm_pctparam.
254 uvm_sysctlpctparam(SYSCTLFN_ARGS
)
257 struct sysctlnode node
;
258 struct uvm_pctparam
*pct
;
260 pct
= rnode
->sysctl_data
;
264 node
.sysctl_data
= &t
;
265 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
266 if (error
|| newp
== NULL
)
269 if (t
< 0 || t
> 100)
272 error
= uvm_pctparam_check(pct
, t
);
276 uvm_pctparam_set(pct
, t
);
282 * uvm_sysctl: sysctl hook into UVM system.
284 SYSCTL_SETUP(sysctl_vm_setup
, "sysctl vm subtree setup")
287 sysctl_createv(clog
, 0, NULL
, NULL
,
289 CTLTYPE_NODE
, "vm", NULL
,
292 sysctl_createv(clog
, 0, NULL
, NULL
,
294 CTLTYPE_STRUCT
, "vmmeter",
295 SYSCTL_DESCR("Simple system-wide virtual memory "
297 sysctl_vm_meter
, 0, NULL
, sizeof(struct vmtotal
),
298 CTL_VM
, VM_METER
, CTL_EOL
);
299 sysctl_createv(clog
, 0, NULL
, NULL
,
301 CTLTYPE_STRUCT
, "loadavg",
302 SYSCTL_DESCR("System load average history"),
303 NULL
, 0, &averunnable
, sizeof(averunnable
),
304 CTL_VM
, VM_LOADAVG
, CTL_EOL
);
305 sysctl_createv(clog
, 0, NULL
, NULL
,
307 CTLTYPE_STRUCT
, "uvmexp",
308 SYSCTL_DESCR("Detailed system-wide virtual memory "
310 sysctl_vm_uvmexp
, 0, &uvmexp
, sizeof(uvmexp
),
311 CTL_VM
, VM_UVMEXP
, CTL_EOL
);
312 sysctl_createv(clog
, 0, NULL
, NULL
,
314 CTLTYPE_INT
, "nkmempages",
315 SYSCTL_DESCR("Default number of pages in kmem_map"),
316 NULL
, 0, &nkmempages
, 0,
317 CTL_VM
, VM_NKMEMPAGES
, CTL_EOL
);
318 sysctl_createv(clog
, 0, NULL
, NULL
,
320 CTLTYPE_STRUCT
, "uvmexp2",
321 SYSCTL_DESCR("Detailed system-wide virtual memory "
323 sysctl_vm_uvmexp2
, 0, NULL
, 0,
324 CTL_VM
, VM_UVMEXP2
, CTL_EOL
);
325 sysctl_createv(clog
, 0, NULL
, NULL
,
326 CTLFLAG_PERMANENT
, CTLTYPE_INT
, "maxslp",
327 SYSCTL_DESCR("Maximum process sleep time before being "
330 CTL_VM
, VM_MAXSLP
, CTL_EOL
);
331 sysctl_createv(clog
, 0, NULL
, NULL
,
332 CTLFLAG_PERMANENT
|CTLFLAG_IMMEDIATE
,
333 CTLTYPE_INT
, "uspace",
334 SYSCTL_DESCR("Number of bytes allocated for a kernel "
336 NULL
, USPACE
, NULL
, 0,
337 CTL_VM
, VM_USPACE
, CTL_EOL
);
338 sysctl_createv(clog
, 0, NULL
, NULL
,
339 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
340 CTLTYPE_INT
, "idlezero",
341 SYSCTL_DESCR("Whether try to zero pages in idle loop"),
342 NULL
, 0, &vm_page_zero_enable
, 0,
343 CTL_VM
, CTL_CREATE
, CTL_EOL
);
345 uvmpdpol_sysctlsetup();
349 * uvm_total: calculate the current state of the system.
352 uvm_total(struct vmtotal
*totalp
)
356 struct vm_map_entry
* entry
;
362 memset(totalp
, 0, sizeof *totalp
);
365 * calculate process statistics
367 mutex_enter(proc_lock
);
368 LIST_FOREACH(l
, &alllwp
, l_list
) {
369 if (l
->l_proc
->p_flag
& PK_SYSTEM
)
377 if (lwp_eprio(l
) <= PZERO
) {
379 } else if (l
->l_slptime
< maxslp
) {
382 if (l
->l_slptime
>= maxslp
)
390 if (l
->l_stat
== LSIDL
)
395 * note active objects
399 * XXXCDC: BOGUS! rethink this. in the mean time
404 for (map
= &p
->p_vmspace
->vm_map
, entry
= map
->header
.next
;
405 entry
!= &map
->header
; entry
= entry
->next
) {
406 if (entry
->is_a_map
|| entry
->is_sub_map
||
407 entry
->object
.uvm_obj
== NULL
)
409 /* XXX how to do this with uvm */
416 mutex_exit(proc_lock
);
419 * Calculate object memory usage statistics.
421 uvm_estimatepageable(&active
, NULL
);
422 totalp
->t_free
= uvmexp
.free
;
423 totalp
->t_vm
= uvmexp
.npages
- uvmexp
.free
+ uvmexp
.swpginuse
;
424 totalp
->t_avm
= active
+ uvmexp
.swpginuse
; /* XXX */
425 totalp
->t_rm
= uvmexp
.npages
- uvmexp
.free
;
426 totalp
->t_arm
= active
;
427 totalp
->t_vmshr
= 0; /* XXX */
428 totalp
->t_avmshr
= 0; /* XXX */
429 totalp
->t_rmshr
= 0; /* XXX */
430 totalp
->t_armshr
= 0; /* XXX */
434 uvm_pctparam_set(struct uvm_pctparam
*pct
, int val
)
438 pct
->pct_scaled
= val
* UVM_PCTPARAM_SCALE
/ 100;
442 uvm_pctparam_get(struct uvm_pctparam
*pct
)
449 uvm_pctparam_check(struct uvm_pctparam
*pct
, int val
)
452 if (pct
->pct_check
== NULL
) {
455 return (*pct
->pct_check
)(pct
, val
);
459 uvm_pctparam_init(struct uvm_pctparam
*pct
, int val
,
460 int (*fn
)(struct uvm_pctparam
*, int))
464 uvm_pctparam_set(pct
, val
);
468 uvm_pctparam_createsysctlnode(struct uvm_pctparam
*pct
, const char *name
,
472 return sysctl_createv(NULL
, 0, NULL
, NULL
,
473 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
474 CTLTYPE_INT
, name
, SYSCTL_DESCR(desc
),
475 uvm_sysctlpctparam
, 0, pct
, 0, CTL_VM
, CTL_CREATE
, CTL_EOL
);