1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#define FOR_vmstat
29#include "toys.h"
30
31struct vmstat_proc {
32
33 uint64_t user, nice, sys, idle, wait, irq, sirq, intr, ctxt, running, blocked;
34
35 uint64_t memfree, buffers, cached, swapfree, swaptotal;
36
37 uint64_t io_in, io_out;
38
39 uint64_t swap_in, swap_out;
40};
41
42
43
44static void get_vmstat_proc(struct vmstat_proc *vmstat_proc)
45{
46 char *vmstuff[] = { "/proc/stat", "cpu ", 0, 0, 0, 0, 0, 0,
47 "intr ", "ctxt ", "procs_running ", "procs_blocked ", "/proc/meminfo",
48 "MemFree: ", "Buffers: ", "Cached: ", "SwapFree: ", "SwapTotal: ",
49 "/proc/vmstat", "pgpgin ", "pgpgout ", "pswpin ", "pswpout " };
50 uint64_t *new = (uint64_t *)vmstat_proc;
51 char *p = p, *name = name;
52 int i, j;
53
54
55
56
57
58
59 for (i = 0; i<sizeof(vmstuff)/sizeof(char *); i++) {
60 if (!vmstuff[i]) p++;
61 else if (*vmstuff[i] == '/') {
62 xreadfile(name = vmstuff[i], toybuf, sizeof(toybuf));
63
64 continue;
65 } else if (!(p = strafter(toybuf, vmstuff[i]))) goto error;
66 if (1 != sscanf(p, "%"PRIu64"%n", new++, &j)) goto error;
67 p += j;
68 }
69
70 return;
71
72error:
73 error_exit("No %sin %s\n", vmstuff[i], name);
74}
75
76void vmstat_main(void)
77{
78 struct vmstat_proc top[2];
79 int i, loop_delay = 0, loop_max = 0;
80 unsigned loop, rows = (toys.optflags & FLAG_n) ? 0 : 25,
81 page_kb = sysconf(_SC_PAGESIZE)/1024;
82 char *headers="r\0b\0swpd\0free\0buff\0cache\0si\0so\0bi\0bo\0in\0cs\0us\0"
83 "sy\0id\0wa", lengths[] = {2,2,6,6,6,6,4,4,5,5,4,4,2,2,2,2};
84
85 memset(top, 0, sizeof(top));
86 if (toys.optc) loop_delay = atolx_range(toys.optargs[0], 0, INT_MAX);
87 if (toys.optc > 1) loop_max = atolx_range(toys.optargs[1], 1, INT_MAX) - 1;
88
89 for (loop = 0; !loop_max || loop <= loop_max; loop++) {
90 unsigned idx = loop&1, offset = 0, expected = 0;
91 uint64_t units, total_hz, *ptr = (uint64_t *)(top+idx),
92 *oldptr = (uint64_t *)(top+!idx);
93
94 if (loop && loop_delay) sleep(loop_delay);
95
96
97 if (rows>3 && !(loop % (rows-3))) {
98 char *header = headers;
99
100 if (isatty(1)) terminal_size(0, &rows);
101 else rows = 0;
102
103 printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n");
104 for (i=0; i<sizeof(lengths); i++) {
105 printf(" %*s"+!i, lengths[i], header);
106 header += strlen(header)+1;
107 }
108 xputc('\n');
109 }
110
111
112 get_vmstat_proc(top+idx);
113 top[idx].running--;
114 top[idx].user += top[idx].nice;
115 top[idx].sys += top[idx].irq + top[idx].sirq;
116 top[idx].swaptotal -= top[idx].swapfree;
117
118
119
120 if (!loop) {
121 char *s = toybuf;
122
123 xreadfile("/proc/uptime", toybuf, sizeof(toybuf));
124 while (*(s++) > ' ');
125 sscanf(s, "%"PRIu64, &units);
126 } else units = loop_delay;
127
128
129
130 total_hz = 0;
131 for (i=0; i<4; i++) total_hz += ptr[i+!!i] - oldptr[i+!!i];
132
133
134
135
136 for (i=0; i<sizeof(lengths); i++) {
137 char order[] = {9, 10, 15, 11, 12, 13, 18, 19, 16, 17, 6, 8, 0, 2, 3, 4};
138 uint64_t out = ptr[order[i]];
139 int len;
140
141
142 if (i>5) out -= oldptr[order[i]];
143 if (order[i]<7) out = ((out*100) + (total_hz/2)) / total_hz;
144 else if (order[i]>17) out = ((out * page_kb)+(units-1))/units;
145 else if (order[i]>15) out = ((out)+(units-1))/units;
146 else if (order[i]<9) out = (out+(units-1)) / units;
147
148
149 expected += lengths[i] + !!i;
150 len = expected - offset - !!i;
151 if (len < 0) len = 0;
152 offset += printf(" %*"PRIu64+!i, len, out);
153 }
154 xputc('\n');
155
156 if (!loop_delay) break;
157 }
158}
159