2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
4 * U.S. Government Rights - Commercial software. Government users are subject
5 * to the Sun Microsystems, Inc. standard license agreement and applicable
6 * provisions of the FAR and its supplements.
9 * This distribution may include materials developed by third parties. Sun,
10 * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
11 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
29 #include <sys/types.h>
31 #include <sys/sysinfo.h>
34 #include <sys/vmmeter.h>
36 static kstat_ctl_t
*kc
; /* libkstat cookie */
38 static kstat_t
**cpu_stat_list
= NULL
;
39 static kstat_t
*sysinfo_ksp
, *vminfo_ksp
, *system_misc_ksp
;
40 static kstat_named_t
*deficit_knp
, *lbolt_knp
, *clk_intr_knp
;
42 static void fail(int, char *, ...);
43 static void safe_zalloc(void **, int, int);
46 cpu_sysinfo_t cpu_sysinfo
;
47 cpu_vminfo_t cpu_vminfo
;
53 static all_stat_t s_new
, s_old
;
55 #define denom(x) ((x) ? (x) : 1)
56 #define DELTA(x) (s_new.x - s_old.x)
62 static void all_stat_init(void);
63 static int all_stat_load(void);
64 static void safe_kstat_read(kstat_ctl_t
*, kstat_t
*, void *);
65 static kstat_t
*safe_kstat_lookup(kstat_ctl_t
*, char *, int, char *);
66 static void *safe_kstat_data_lookup(kstat_t
*, char *);
68 static int fr_time
= 0;
69 /* Get CPU Process details from kstats-
70 * Number of processes in runqueue,
71 * waiting and swapqueue
74 krgetprocdetail(int *runque
, int *waiting
, int *swapque
)
79 /* Initialize a kstat control structure */
80 if ((kc
= kstat_open()) == NULL
)
81 fail(1, "kstat_open(): can't open /dev/kstat");
86 /* update the kstat header chain or load all_stat structure */
87 while (kstat_chain_update(kc
) || all_stat_load()) {
91 updates
= denom(DELTA(sysinfo
.updates
));
93 #define ADJ(n) ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj)
94 #define adjprintf(fmt, n, val) adj -= (n + 1) - printf(fmt, ADJ(n), val)
96 *runque
= DELTA(sysinfo
.runque
) / updates
;
97 *waiting
= DELTA(sysinfo
.waiting
) / updates
;
98 *swapque
= DELTA(sysinfo
.swpque
) / updates
;
101 * Close the kstat control structure and set it to null.
104 kc = (kstat_ctl_t *)NULL;*/
110 /* Get RAm details from kstats */
112 krgetramdetail(int *handspread
, int *scan
)
115 int pages
, handspreadpages
;
117 pagesize
= sysconf(_SC_PAGESIZE
);
118 hz
= sysconf(_SC_CLK_TCK
);
120 /* default max handspread is 64MB worth of pages */
121 handspreadpages
= (64 * 1048576)/sysconf(_SC_PAGESIZE
);
122 pages
= sysconf(_SC_PHYS_PAGES
);
125 if ((kc
= kstat_open()) == NULL
) {
126 fail(1, "kstat_open(): can't open /dev/kstat");
129 /* Initialize the all_stat structure */
134 if (handspreadpages
> (pages
/4)) {
135 handspreadpages
= (int)(pages
/4);
137 /* update the kstat header chain or load all_stat structure */
138 while (kstat_chain_update(kc
) || all_stat_load())
139 /* (void) printf("<<State change>>\n"); */
144 for (i
= 0; i
< CPU_STATES
; i
++)
145 etime
+= DELTA(cpu_sysinfo
.cpu
[i
]);
147 etime
= denom(((etime
/ ncpus
) + (hz
>> 1)) / hz
);
149 *handspread
= handspreadpages
;
150 *scan
= DELTA(cpu_vminfo
.scan
) / etime
;
153 * Close the kstat control structure and set it to null.
156 kc = (kstat_ctl_t *)NULL;
161 /* Get ncstat data */
163 krgetncstatdetail(unsigned long *hits
, unsigned long *misses
)
165 struct ncstats ncstats
;
168 /* Initialize the all_stat structure */
169 if ((kc
= kstat_open()) == NULL
) {
170 fail(1, "kstat_open(): can't open /dev/kstat");
173 /* Initialize the all_stat structure */
178 if (all_stat_load() != 0)
179 fail(1, "all_stat_load() failed");
181 safe_kstat_read(kc
, safe_kstat_lookup(kc
, "unix", 0, "ncstats"), (void *) &ncstats
);
183 *hits
= (unsigned long)ncstats
.hits
;
184 *misses
= (unsigned long)ncstats
.misses
;
187 * Close the kstat control structure and set it to null.
190 kc = (kstat_ctl_t *)NULL;
195 /* Initialize the all_stat structure */
205 sysinfo_ksp
= safe_kstat_lookup(kc
, "unix", 0, "sysinfo");
206 vminfo_ksp
= safe_kstat_lookup(kc
, "unix", 0, "vminfo");
207 system_misc_ksp
= safe_kstat_lookup(kc
, "unix", 0, "system_misc");
209 safe_kstat_read(kc
, system_misc_ksp
, NULL
);
210 deficit_knp
= safe_kstat_data_lookup(system_misc_ksp
, "deficit");
211 lbolt_knp
= safe_kstat_data_lookup(system_misc_ksp
, "lbolt");
212 clk_intr_knp
= safe_kstat_data_lookup(system_misc_ksp
, "clk_intr");
219 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
)
220 if (strncmp(ksp
->ks_name
, "cpu_stat", 8) == 0)
223 safe_zalloc((void **) &cpu_stat_list
, ncpus
* sizeof (kstat_t
*), 1);
226 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
)
227 if (strncmp(ksp
->ks_name
, "cpu_stat", 8) == 0 &&
228 kstat_read(kc
, ksp
, NULL
) != -1)
229 cpu_stat_list
[ncpus
++] = ksp
;
232 fail(0, "can't find any cpu statistics");
234 (void) memset(&s_new
, 0, sizeof (all_stat_t
));
238 * load statistics, summing across CPUs where needed
249 (void) memset(&s_new
, 0, sizeof (all_stat_t
));
255 safe_kstat_read(kc
, sysinfo_ksp
, (void *) &s_new
.sysinfo
);
256 safe_kstat_read(kc
, vminfo_ksp
, (void *) &s_new
.vminfo
);
257 safe_kstat_read(kc
, system_misc_ksp
, NULL
);
258 s_new
.deficit
= deficit_knp
->value
.l
;
261 * Per-CPU statistics.
262 * For now, we just sum across all CPUs. In the future,
263 * we should add options to vmstat for per-CPU data.
266 for (i
= 0; i
< ncpus
; i
++) {
267 if (kstat_read(kc
, cpu_stat_list
[i
], (void *) &cs
) == -1)
269 np
= (uint
*) &s_new
.cpu_sysinfo
;
270 tp
= (uint
*) &cs
.cpu_sysinfo
;
271 for (j
= 0; j
< sizeof (cpu_sysinfo_t
); j
+= sizeof (uint_t
))
273 np
= (uint
*) &s_new
.cpu_vminfo
;
274 tp
= (uint
*) &cs
.cpu_vminfo
;
275 for (j
= 0; j
< sizeof (cpu_vminfo_t
); j
+= sizeof (uint_t
))
282 fail(int do_perror
, char *message
, ...)
285 int save_errno
= errno
;
287 va_start(args
, message
);
288 (void) vfprintf(stderr
, message
, args
);
291 (void) fprintf(stderr
, ": %s", strerror(save_errno
));
292 (void) fprintf(stderr
, "\n");
297 safe_zalloc(void **ptr
, int size
, int free_first
)
299 if (free_first
&& *ptr
!= NULL
)
301 if ((*ptr
= (void *) malloc(size
)) == NULL
)
302 fail(1, "malloc failed");
303 (void) memset(*ptr
, 0, size
);
308 safe_kstat_read(kstat_ctl_t
*kc
, kstat_t
*ksp
, void *data
)
310 kid_t kstat_chain_id
= kstat_read(kc
, ksp
, data
);
312 if (kstat_chain_id
== -1)
313 fail(1, "kstat_read(%x, '%s') failed", kc
, ksp
->ks_name
);
317 safe_kstat_lookup(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
,
320 kstat_t
*ksp
= kstat_lookup(kc
, ks_module
, ks_instance
, ks_name
);
323 fail(0, "kstat_lookup('%s', %d, '%s') failed",
324 ks_module
== NULL
? "" : ks_module
,
326 ks_name
== NULL
? "" : ks_name
);
331 safe_kstat_data_lookup(kstat_t
*ksp
, char *name
)
333 void *fp
= kstat_data_lookup(ksp
, name
);
336 fail(0, "kstat_data_lookup('%s', '%s') failed",