1 /* $NetBSD: vmstat.c,v 1.74 2009/10/21 13:56:36 wiz Exp $ */
4 * Copyright (c) 1983, 1989, 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
37 __RCSID("$NetBSD: vmstat.c,v 1.74 2009/10/21 13:56:36 wiz Exp $");
41 * Cursed vmstat -- from Robert Elz.
44 #include <sys/param.h>
46 #include <sys/namei.h>
47 #include <sys/sysctl.h>
48 #include <sys/evcnt.h>
50 #include <uvm/uvm_extern.h>
60 #include "utmpentry.h"
64 struct uvmexp_sysctl uvmexp
;
66 struct nchstats nchstats
;
72 enum display_mode display_mode
= TIME
;
74 static void allocinfo(struct Info
*);
75 static void copyinfo(struct Info
*, struct Info
*);
76 static float cputime(int);
77 static void dinfo(int, int, int);
78 static void getinfo(struct Info
*);
79 static int ucount(void);
82 static u_int64_t temp
;
87 static char **intrname
;
88 static int nextintsrow
;
89 static int disk_horiz
= 1;
98 closevmstat(WINDOW
*w
)
108 static struct nlist namelist
[] = {
110 { .n_name
= "_nchstats" },
111 #define X_INTRNAMES 1
112 { .n_name
= "_intrnames" },
113 #define X_EINTRNAMES 2
114 { .n_name
= "_eintrnames" },
116 { .n_name
= "_intrcnt" },
118 { .n_name
= "_eintrcnt" },
119 #define X_ALLEVENTS 5
120 { .n_name
= "_allevents" },
125 * These constants define where the major pieces are laid out
127 #define STATROW 0 /* uses 1 row and 68 cols */
129 #define MEMROW 9 /* uses 4 rows and 31 cols */
131 #define PAGEROW 2 /* uses 4 rows and 26 cols */
133 #define INTSROW 9 /* uses all rows to bottom and 17 cols */
135 #define INTSCOLEND (VMSTATCOL - 0)
136 #define PROCSROW 2 /* uses 2 rows and 20 cols */
138 #define GENSTATROW 2 /* uses 2 rows and 30 cols */
139 #define GENSTATCOL 17
140 #define VMSTATROW 7 /* uses 17 rows and 15 cols */
142 #define GRAPHROW 5 /* uses 3 rows and 51 cols */
144 #define NAMEIROW 14 /* uses 3 rows and 38 cols */
146 #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */
148 #define DISKCOLWIDTH 6
149 #define DISKCOLEND INTSCOL
151 typedef struct intr_evcnt intr_evcnt_t
;
155 u_int64_t
*ie_count
; /* kernel address... */
156 int ie_loc
; /* screen row */
161 get_interrupt_events(void)
163 struct evcntlist allevents
;
164 struct evcnt evcnt
, *evptr
;
168 if (!NREAD(X_ALLEVENTS
, &allevents
, sizeof allevents
))
170 evptr
= TAILQ_FIRST(&allevents
);
171 for (; evptr
!= NULL
; evptr
= TAILQ_NEXT(&evcnt
, ev_list
)) {
172 if (!KREAD(evptr
, &evcnt
, sizeof evcnt
))
174 if (evcnt
.ev_type
!= EVCNT_TYPE_INTR
)
176 n
= realloc(ie_head
, sizeof *ie
* (nevcnt
+ 1));
178 error("realloc failed");
182 ie
= ie_head
+ nevcnt
;
183 ie
->ie_group
= malloc(evcnt
.ev_grouplen
+ 1);
184 ie
->ie_name
= malloc(evcnt
.ev_namelen
+ 1);
185 if (ie
->ie_group
== NULL
|| ie
->ie_name
== NULL
)
187 if (!KREAD(evcnt
.ev_group
, ie
->ie_group
, evcnt
.ev_grouplen
+ 1))
189 if (!KREAD(evcnt
.ev_name
, ie
->ie_name
, evcnt
.ev_namelen
+ 1))
191 ie
->ie_count
= &evptr
->ev_count
;
200 static char *intrnamebuf
;
211 if (namelist
[0].n_type
== 0) {
212 if (kvm_nlist(kd
, namelist
) &&
213 (namelist
[X_NCHSTATS
].n_type
== 0 ||
214 namelist
[X_ALLEVENTS
].n_type
== 0)) {
218 if (namelist
[0].n_type
== 0) {
219 error("No namelist");
223 hertz
= stathz
? stathz
: hz
;
227 /* Old style interrupt counts - deprecated */
228 nintr
= (namelist
[X_EINTRCNT
].n_value
-
229 namelist
[X_INTRCNT
].n_value
) / sizeof (long);
231 intrloc
= calloc(nintr
, sizeof (long));
232 intrname
= calloc(nintr
, sizeof (long));
233 intrnamebuf
= malloc(namelist
[X_EINTRNAMES
].n_value
-
234 namelist
[X_INTRNAMES
].n_value
);
235 if (intrnamebuf
== NULL
|| intrname
== 0 || intrloc
== 0) {
236 error("Out of memory\n");
240 NREAD(X_INTRNAMES
, intrnamebuf
, NVAL(X_EINTRNAMES
) -
242 for (cp
= intrnamebuf
, i
= 0; i
< nintr
; i
++) {
244 cp
+= strlen(cp
) + 1;
248 /* event counter interrupt counts */
249 get_interrupt_events();
251 nextintsrow
= INTSROW
+ 1;
268 strlcpy(buf
, ctime(&now
), sizeof(buf
));
274 print_ie_title(int i
)
276 int width
, name_width
, group_width
;
278 width
= INTSCOLEND
- (INTSCOL
+ 9);
282 move(ie_head
[i
].ie_loc
, INTSCOL
+ 9);
283 group_width
= strlen(ie_head
[i
].ie_group
);
284 name_width
= strlen(ie_head
[i
].ie_name
);
285 width
-= group_width
+ 1 + name_width
;
288 * Screen to narrow for full strings
289 * This is all rather horrid, in some cases there are a lot
290 * of events in the same group, and in others the event
291 * name is "intr". There are also names which need 7 or 8
292 * columns before they become meaningful.
293 * This is a bad compromise.
296 group_width
-= (width
+ 1) / 2;
297 name_width
-= width
/ 2;
298 /* some have the 'useful' name "intr", display their group */
299 if (strcasecmp(ie_head
[i
].ie_name
, "intr") == 0) {
300 group_width
+= name_width
+ 1;
303 if (group_width
<= 3 || name_width
< 0) {
304 /* don't display group */
305 name_width
+= group_width
+ 1;
311 if (group_width
!= 0) {
312 printw("%-.*s", group_width
, ie_head
[i
].ie_group
);
317 printw("%-.*s", name_width
, ie_head
[i
].ie_name
);
321 labelvmstat_top(void)
326 mvprintw(STATROW
, STATCOL
+ 4, "users Load");
328 mvprintw(GENSTATROW
, GENSTATCOL
, " Csw Trp Sys Int Sof Flt");
330 mvprintw(GRAPHROW
, GRAPHCOL
,
331 " . %% Sy . %% Us . %% Ni . %% In . %% Id");
332 mvprintw(PROCSROW
, PROCSCOL
, "Proc:r d s");
333 mvprintw(GRAPHROW
+ 1, GRAPHCOL
,
334 "| | | | | | | | | | |");
336 mvprintw(PAGEROW
, PAGECOL
+ 8, "PAGING SWAPPING ");
337 mvprintw(PAGEROW
+ 1, PAGECOL
, " in out in out ");
338 mvprintw(PAGEROW
+ 2, PAGECOL
+ 2, "ops");
339 mvprintw(PAGEROW
+ 3, PAGECOL
, "pages");
347 /* Top few lines first */
351 /* Left hand column */
353 mvprintw(MEMROW
, MEMCOL
, " memory totals (in kB)");
354 mvprintw(MEMROW
+ 1, MEMCOL
, " real virtual free");
355 mvprintw(MEMROW
+ 2, MEMCOL
, "Active");
356 mvprintw(MEMROW
+ 3, MEMCOL
, "All");
358 mvprintw(NAMEIROW
, NAMEICOL
, "Namei Sys-cache Proc-cache");
359 mvprintw(NAMEIROW
+ 1, NAMEICOL
,
360 " Calls hits %% hits %%");
362 mvprintw(DISKROW
, DISKCOL
, "Disks:");
364 mvprintw(DISKROW
+ 1, DISKCOL
+ 1, "seeks");
365 mvprintw(DISKROW
+ 2, DISKCOL
+ 1, "xfers");
366 mvprintw(DISKROW
+ 3, DISKCOL
+ 1, "bytes");
367 mvprintw(DISKROW
+ 4, DISKCOL
+ 1, "%%busy");
369 mvprintw(DISKROW
, DISKCOL
+ 1 + 1 * DISKCOLWIDTH
, "seeks");
370 mvprintw(DISKROW
, DISKCOL
+ 1 + 2 * DISKCOLWIDTH
, "xfers");
371 mvprintw(DISKROW
, DISKCOL
+ 1 + 3 * DISKCOLWIDTH
, "bytes");
372 mvprintw(DISKROW
, DISKCOL
+ 1 + 4 * DISKCOLWIDTH
, "%%busy");
377 mvprintw(INTSROW
, INTSCOL
+ 9, "Interrupts");
378 for (i
= 0; i
< nintr
; i
++) {
381 mvprintw(intrloc
[i
], INTSCOL
+ 9, "%-.*s",
382 INTSCOLEND
- (INTSCOL
+ 9), intrname
[i
]);
384 for (i
= 0; i
< nevcnt
; i
++) {
385 if (ie_head
[i
].ie_loc
== 0)
390 /* Right hand column */
392 mvprintw(VMSTATROW
+ 0, VMSTATCOL
+ 10, "forks");
393 mvprintw(VMSTATROW
+ 1, VMSTATCOL
+ 10, "fkppw");
394 mvprintw(VMSTATROW
+ 2, VMSTATCOL
+ 10, "fksvm");
395 mvprintw(VMSTATROW
+ 3, VMSTATCOL
+ 10, "pwait");
396 mvprintw(VMSTATROW
+ 4, VMSTATCOL
+ 10, "relck");
397 mvprintw(VMSTATROW
+ 5, VMSTATCOL
+ 10, "rlkok");
398 mvprintw(VMSTATROW
+ 6, VMSTATCOL
+ 10, "noram");
399 mvprintw(VMSTATROW
+ 7, VMSTATCOL
+ 10, "ndcpy");
400 mvprintw(VMSTATROW
+ 8, VMSTATCOL
+ 10, "fltcp");
401 mvprintw(VMSTATROW
+ 9, VMSTATCOL
+ 10, "zfod");
402 mvprintw(VMSTATROW
+ 10, VMSTATCOL
+ 10, "cow");
403 mvprintw(VMSTATROW
+ 11, VMSTATCOL
+ 10, "fmin");
404 mvprintw(VMSTATROW
+ 12, VMSTATCOL
+ 10, "ftarg");
405 mvprintw(VMSTATROW
+ 13, VMSTATCOL
+ 10, "itarg");
406 mvprintw(VMSTATROW
+ 14, VMSTATCOL
+ 10, "wired");
407 mvprintw(VMSTATROW
+ 15, VMSTATCOL
+ 10, "pdfre");
409 if (LINES
- 1 > VMSTATROW
+ 16)
410 mvprintw(VMSTATROW
+ 16, VMSTATCOL
+ 10, "pdscn");
413 #define X(s, s1, fld) {temp = (s).fld[i]; (s).fld[i] -= (s1).fld[i]; \
414 if (display_mode == TIME) (s1).fld[i] = temp;}
415 #define Z(s, s1, fld) {temp = (s).nchstats.fld; \
416 (s).nchstats.fld -= (s1).nchstats.fld; \
417 if (display_mode == TIME) (s1).nchstats.fld = temp;}
418 #define PUTRATE(s, s1, fld, l, c, w) \
419 {temp = (s).fld; (s).fld -= (s1).fld; \
420 if (display_mode == TIME) (s1).fld = temp; \
421 putint((int)((float)(s).fld/etime + 0.5), l, c, w);}
424 static char cpuchar
[CPUSTATES
] = { '=' , '>', '-', '%', ' ' };
425 static char cpuorder
[CPUSTATES
] = { CP_SYS
, CP_USER
, CP_NICE
, CP_INTR
, CP_IDLE
};
428 show_vmstat_top(vmtotal_t
*Total
, uvmexp_sysctl_t
*uvm
, uvmexp_sysctl_t
*uvm1
)
434 struct uvmexp_sysctl
*uvmexp
;
440 putint(ucount(), STATROW
, STATCOL
, 3);
441 putfloat(avenrun
[0], STATROW
, STATCOL
+ 17, 6, 2, 0);
442 putfloat(avenrun
[1], STATROW
, STATCOL
+ 23, 6, 2, 0);
443 putfloat(avenrun
[2], STATROW
, STATCOL
+ 29, 6, 2, 0);
444 mvaddstr(STATROW
, STATCOL
+ 53, buf
);
446 putint(Total
->t_rq
- 1, PROCSROW
+ 1, PROCSCOL
+ 3, 3);
447 putint(Total
->t_dw
, PROCSROW
+ 1, PROCSCOL
+ 6, 3);
448 putint(Total
->t_sl
, PROCSROW
+ 1, PROCSCOL
+ 9, 3);
450 PUTRATE(us
, us1
, uvmexp
->swtch
, GENSTATROW
+ 1, GENSTATCOL
- 1, 7);
451 PUTRATE(us
, us1
, uvmexp
->traps
, GENSTATROW
+ 1, GENSTATCOL
+ 7, 6);
452 PUTRATE(us
, us1
, uvmexp
->syscalls
, GENSTATROW
+ 1, GENSTATCOL
+ 14, 6);
453 PUTRATE(us
, us1
, uvmexp
->intrs
, GENSTATROW
+ 1, GENSTATCOL
+ 21, 5);
454 PUTRATE(us
, us1
, uvmexp
->softs
, GENSTATROW
+ 1, GENSTATCOL
+ 27, 6);
455 PUTRATE(us
, us1
, uvmexp
->faults
, GENSTATROW
+ 1, GENSTATCOL
+ 34, 6);
457 /* Last CPU state not calculated yet. */
458 for (f2
= 0.0, psiz
= 0, c
= 0; c
< CPUSTATES
; c
++) {
462 l
= (int) ((f2
+ 1.0) / 2.0) - psiz
;
464 putfloat(f1
, GRAPHROW
, GRAPHCOL
+ 1, 5, 1, 0);
466 putfloat(f1
, GRAPHROW
, GRAPHCOL
+ 10 * c
+ 1, 5, 1, 0);
467 mvhline(GRAPHROW
+ 2, psiz
, cpuchar
[c
], l
);
471 PUTRATE(us
, us1
, uvmexp
->pageins
, PAGEROW
+ 2, PAGECOL
+ 5, 5);
472 PUTRATE(us
, us1
, uvmexp
->pdpageouts
, PAGEROW
+ 2, PAGECOL
+ 10, 5);
473 PUTRATE(us
, us1
, uvmexp
->pgswapin
, PAGEROW
+ 3, PAGECOL
+ 5, 5);
474 PUTRATE(us
, us1
, uvmexp
->pgswapout
, PAGEROW
+ 3, PAGECOL
+ 10, 5);
482 static int failcnt
= 0;
483 static int relabel
= 0;
484 static int last_disks
= 0;
485 static char pigs
[] = "pigs";
493 if (display_mode
== TIME
) {
495 etime
= cur
.cp_etime
;
496 /* < 5 ticks - ignore this trash */
497 if ((etime
* hertz
) < 1.0) {
498 if (failcnt
++ <= MAXFAIL
)
501 mvprintw(2, 10, "The alternate system clock has died!");
502 mvprintw(3, 10, "Reverting to ``pigs'' display.");
513 show_vmstat_top(&s
.Total
, &s
.uvmexp
, &s1
.uvmexp
);
516 #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024))
517 putint(pgtokb(s
.uvmexp
.active
), MEMROW
+ 2, MEMCOL
+ 6, 8);
518 putint(pgtokb(s
.uvmexp
.active
+ s
.uvmexp
.swpginuse
), /* XXX */
519 MEMROW
+ 2, MEMCOL
+ 15, 8);
520 putint(pgtokb(s
.uvmexp
.npages
- s
.uvmexp
.free
), MEMROW
+ 3, MEMCOL
+ 6, 8);
521 putint(pgtokb(s
.uvmexp
.npages
- s
.uvmexp
.free
+ s
.uvmexp
.swpginuse
),
522 MEMROW
+ 3, MEMCOL
+ 15, 8);
523 putint(pgtokb(s
.uvmexp
.free
), MEMROW
+ 2, MEMCOL
+ 24, 8);
524 putint(pgtokb(s
.uvmexp
.free
+ s
.uvmexp
.swpages
- s
.uvmexp
.swpginuse
),
525 MEMROW
+ 3, MEMCOL
+ 24, 8);
529 Z(s
, s1
, ncs_goodhits
); Z(s
, s1
, ncs_badhits
); Z(s
, s1
, ncs_miss
);
530 Z(s
, s1
, ncs_long
); Z(s
, s1
, ncs_pass2
); Z(s
, s1
, ncs_2passes
);
531 s
.nchcount
= s
.nchstats
.ncs_goodhits
+ s
.nchstats
.ncs_badhits
+
532 s
.nchstats
.ncs_miss
+ s
.nchstats
.ncs_long
;
533 if (display_mode
== TIME
)
534 s1
.nchcount
= s
.nchcount
;
536 putint(s
.nchcount
, NAMEIROW
+ 2, NAMEICOL
, 9);
537 putint(s
.nchstats
.ncs_goodhits
, NAMEIROW
+ 2, NAMEICOL
+ 9, 9);
538 #define nz(x) ((x) ? (x) : 1)
539 putfloat(s
.nchstats
.ncs_goodhits
* 100.0 / nz(s
.nchcount
),
540 NAMEIROW
+ 2, NAMEICOL
+ 19, 4, 0, 1);
541 putint(s
.nchstats
.ncs_pass2
, NAMEIROW
+ 2, NAMEICOL
+ 23, 9);
542 putfloat(s
.nchstats
.ncs_pass2
* 100.0 / nz(s
.nchcount
),
543 NAMEIROW
+ 2, NAMEICOL
+ 34, 4, 0, 1);
547 for (l
= 0, i
= 0, r
= DISKROW
, c
= DISKCOL
;
548 i
< (int)ndrive
; i
++) {
556 if (c
+ DISKCOLWIDTH
> DISKCOLEND
) {
557 if (disk_horiz
&& LINES
- 1 - DISKROW
>
558 (DISKCOLEND
- DISKCOL
) / DISKCOLWIDTH
) {
564 if (r
>= LINES
- 1) {
565 if (!disk_horiz
&& LINES
- 1 - DISKROW
<
566 (DISKCOLEND
- DISKCOL
) / DISKCOLWIDTH
) {
576 /* blank out if we lost any disks */
577 for (i
= l
; i
< last_disks
; i
++) {
583 for (j
= 0; j
< 5; j
++) {
585 mvprintw(r
+j
, c
, "%*s", DISKCOLWIDTH
, "");
587 mvprintw(r
, c
+j
*DISKCOLWIDTH
, "%*s", DISKCOLWIDTH
, "");
595 for (i
= 0; i
< nintr
; i
++) {
596 if (s
.intrcnt
[i
] == 0)
598 if (intrloc
[i
] == 0) {
599 if (nextintsrow
== LINES
)
601 intrloc
[i
] = nextintsrow
++;
602 mvprintw(intrloc
[i
], INTSCOL
+ 9, "%-.*s",
603 INTSCOLEND
- (INTSCOL
+ 9), intrname
[i
]);
606 l
= (int)((float)s
.intrcnt
[i
]/etime
+ 0.5);
608 putint(l
, intrloc
[i
], INTSCOL
, 8);
611 for (i
= 0; i
< nevcnt
; i
++) {
614 if (ie_head
[i
].ie_loc
== 0) {
615 if (nextintsrow
== LINES
)
617 ie_head
[i
].ie_loc
= nextintsrow
++;
621 l
= (int)((float)s
.evcnt
[i
]/etime
+ 0.5);
623 putint(l
, ie_head
[i
].ie_loc
, INTSCOL
, 8);
625 putint(inttotal
, INTSROW
, INTSCOL
, 8);
627 PUTRATE(s
, s1
, uvmexp
.forks
, VMSTATROW
+ 0, VMSTATCOL
+ 3, 6);
628 PUTRATE(s
, s1
, uvmexp
.forks_ppwait
, VMSTATROW
+ 1, VMSTATCOL
+ 3, 6);
629 PUTRATE(s
, s1
, uvmexp
.forks_sharevm
, VMSTATROW
+ 2, VMSTATCOL
+ 3, 6);
630 PUTRATE(s
, s1
, uvmexp
.fltpgwait
, VMSTATROW
+ 3, VMSTATCOL
+ 4, 5);
631 PUTRATE(s
, s1
, uvmexp
.fltrelck
, VMSTATROW
+ 4, VMSTATCOL
+ 3, 6);
632 PUTRATE(s
, s1
, uvmexp
.fltrelckok
, VMSTATROW
+ 5, VMSTATCOL
+ 3, 6);
633 PUTRATE(s
, s1
, uvmexp
.fltnoram
, VMSTATROW
+ 6, VMSTATCOL
+ 3, 6);
634 PUTRATE(s
, s1
, uvmexp
.fltamcopy
, VMSTATROW
+ 7, VMSTATCOL
+ 3, 6);
635 PUTRATE(s
, s1
, uvmexp
.flt_prcopy
, VMSTATROW
+ 8, VMSTATCOL
+ 3, 6);
636 PUTRATE(s
, s1
, uvmexp
.flt_przero
, VMSTATROW
+ 9, VMSTATCOL
+ 3, 6);
637 PUTRATE(s
, s1
, uvmexp
.flt_acow
, VMSTATROW
+ 10, VMSTATCOL
, 9);
638 putint(s
.uvmexp
.freemin
, VMSTATROW
+ 11, VMSTATCOL
, 9);
639 putint(s
.uvmexp
.freetarg
, VMSTATROW
+ 12, VMSTATCOL
, 9);
640 putint(s
.uvmexp
.inactarg
, VMSTATROW
+ 13, VMSTATCOL
, 9);
641 putint(s
.uvmexp
.wired
, VMSTATROW
+ 14, VMSTATCOL
, 9);
642 PUTRATE(s
, s1
, uvmexp
.pdfreed
, VMSTATROW
+ 15, VMSTATCOL
, 9);
643 if (LINES
- 1 > VMSTATROW
+ 16)
644 PUTRATE(s
, s1
, uvmexp
.pdscans
, VMSTATROW
+ 16, VMSTATCOL
, 9);
649 vmstat_boot(char *args
)
656 vmstat_run(char *args
)
663 vmstat_time(char *args
)
669 vmstat_zero(char *args
)
671 if (display_mode
== RUN
)
675 /* calculate number of users on the system */
679 static int onusers
= -1;
681 struct utmpentry
*ehead
;
683 nusers
= getutentries(NULL
, &ehead
);
685 if (nusers
!= onusers
) {
687 mvprintw(STATROW
, STATCOL
+ 8, " ");
689 mvprintw(STATROW
, STATCOL
+ 8, "s");
702 for (i
= 0; i
< CPUSTATES
; i
++)
706 return (cur
.cp_time
[indx
] * 100.0 / t
);
710 puthumanint(u_int64_t n
, int l
, int c
, int w
)
714 if (move(l
, c
) != OK
)
720 if (humanize_number(b
, w
, n
, "", HN_AUTOSCALE
, HN_NOSPACE
) == -1 ) {
728 putint(int n
, int l
, int c
, int w
)
732 if (move(l
, c
) != OK
)
738 (void)snprintf(b
, sizeof b
, "%*d", w
, n
);
739 if ((int)strlen(b
) > w
) {
740 if (display_mode
== TIME
)
743 puthumanint(n
, l
, c
, w
);
750 putfloat(double f
, int l
, int c
, int w
, int d
, int nz
)
754 if (move(l
, c
) != OK
)
756 if (nz
&& f
== 0.0) {
760 (void)snprintf(b
, sizeof b
, "%*.*f", w
, d
, f
);
761 if ((int)strlen(b
) > w
) {
769 getinfo(struct Info
*stats
)
777 NREAD(X_NCHSTATS
, &stats
->nchstats
, sizeof stats
->nchstats
);
779 NREAD(X_INTRCNT
, stats
->intrcnt
, nintr
* LONG
);
780 for (i
= 0; i
< nevcnt
; i
++)
781 KREAD(ie_head
[i
].ie_count
, &stats
->evcnt
[i
],
782 sizeof stats
->evcnt
[i
]);
783 size
= sizeof(stats
->uvmexp
);
786 if (sysctl(mib
, 2, &stats
->uvmexp
, &size
, NULL
, 0) < 0) {
787 error("can't get uvmexp: %s\n", strerror(errno
));
788 memset(&stats
->uvmexp
, 0, sizeof(stats
->uvmexp
));
790 size
= sizeof(stats
->Total
);
793 if (sysctl(mib
, 2, &stats
->Total
, &size
, NULL
, 0) < 0) {
794 error("Can't get kernel info: %s\n", strerror(errno
));
795 memset(&stats
->Total
, 0, sizeof(stats
->Total
));
800 allocinfo(struct Info
*stats
)
804 (stats
->intrcnt
= calloc(nintr
, sizeof(long))) == NULL
) {
805 error("calloc failed");
808 if ((stats
->evcnt
= calloc(nevcnt
, sizeof(u_int64_t
))) == NULL
) {
809 error("calloc failed");
815 copyinfo(struct Info
*from
, struct Info
*to
)
820 intrcnt
= to
->intrcnt
;
823 memmove(to
->intrcnt
= intrcnt
, from
->intrcnt
, nintr
* sizeof *intrcnt
);
824 memmove(to
->evcnt
= evcnt
, from
->evcnt
, nevcnt
* sizeof *evcnt
);
828 dinfo(int dn
, int r
, int c
)
831 #define ADV if (disk_horiz) r++; else c += DISKCOLWIDTH
833 mvprintw(r
, c
, "%*.*s", DISKCOLWIDTH
, DISKCOLWIDTH
, dr_name
[dn
]);
836 putint((int)(cur
.seek
[dn
]/etime
+0.5), r
, c
, DISKCOLWIDTH
);
838 putint((int)((cur
.rxfer
[dn
]+cur
.wxfer
[dn
])/etime
+0.5),
841 puthumanint((cur
.rbytes
[dn
] + cur
.wbytes
[dn
]) / etime
+ 0.5,
845 /* time busy in disk activity */
846 atime
= cur
.time
[dn
].tv_sec
+ cur
.time
[dn
].tv_usec
/ 1000000.0;
847 atime
= atime
* 100.0 / etime
;
849 putint(100, r
, c
, DISKCOLWIDTH
);
851 putfloat(atime
, r
, c
, DISKCOLWIDTH
, 1, 1);