4 * System information gathering for Solaris
14 #include <sys/sysinfo.h>
18 * The index field is for a fast lookup on the string.
19 * A -1 tells stat_data_lookup() that we need to locate
20 * the string. Once stat_data_lookup() has located the
21 * string, it will set the index of were we found it.
23 typedef struct cpu_states_info
{
29 static struct cpu_states_info cpu_states
[CPU_STATES
] = {
30 {"cpu_ticks_idle", -1},
31 {"cpu_ticks_user", -1},
32 {"cpu_ticks_kernel", -1},
33 {"cpu_ticks_wait", -1}
36 static kstat_ctl_t
*kcp
= NULL
;
37 static kstat_t
*ksp_old
;
39 static uint64_t physmem
= 0;
41 /* NumCPUs_DoInit returns the number of CPUs present in the system and
42 performs any initialization necessary for the sysinfo-XXX module */
43 unsigned int NumCpus_DoInit(void)
52 physmem
= sysconf(_SC_PHYS_PAGES
);
53 smp_num_cpus
= sysconf(_SC_NPROCESSORS_CONF
);
54 if (smp_num_cpus
< 1) {
55 smp_num_cpus
= 1; /* SPARC glibc is buggy */
58 if (smp_num_cpus
> 255) {
59 /* we don't support more than 255 CPUs (well, in fact no more
60 than two ate the moment... */
64 ksp_old
= malloc(smp_num_cpus
* sizeof (kstat_t
));
65 if (ksp_old
== NULL
) {
67 fprintf(stderr
, "ERROR: Can't allocate cpu load history.\n");
71 for (i
= 0; i
< smp_num_cpus
; i
++) {
72 ksp_old
[i
].ks_data
= NULL
;
73 ksp_old
[i
].ks_data_size
= 0;
80 * If index_ptr integer value is > -1 then the index points to the
81 * string entry in the ks_data that we are interested in. Otherwise
82 * we will need to walk the array.
84 void *stat_data_lookup(kstat_t
*ksp
, char *name
, int *index_ptr
)
91 switch (ksp
->ks_type
) {
92 case KSTAT_TYPE_NAMED
:
93 size
= sizeof (kstat_named_t
);
94 namep
= KSTAT_NAMED_PTR(ksp
)->name
;
96 case KSTAT_TYPE_TIMER
:
97 size
= sizeof (kstat_timer_t
);
98 namep
= KSTAT_TIMER_PTR(ksp
)->name
;
107 /* Short cut to the information. */
108 datap
= ksp
->ks_data
;
109 datap
= &datap
[size
*index
];
113 /* Need to go find the string. */
114 datap
= ksp
->ks_data
;
115 for (i
= 0; i
< ksp
->ks_ndata
; i
++) {
116 if (strcmp(name
, namep
) == 0) {
127 uint64_t kstat_delta(kstat_t
*old
, kstat_t
*new, char *name
, int *index
)
129 kstat_named_t
*knew
= stat_data_lookup(new, name
, index
);
131 if (old
&& old
->ks_data
) {
132 kstat_named_t
*kold
= stat_data_lookup(old
, name
, index
);
133 return (knew
->value
.ui64
- kold
->value
.ui64
);
135 return (knew
->value
.ui64
);
138 uint64_t cpu_ticks_delta(kstat_t
*old
, kstat_t
*new)
143 for (i
= 0; i
< CPU_STATES
; i
++) {
144 ticks
+= kstat_delta(old
, new, cpu_states
[i
].field_name
,
145 &cpu_states
[i
].index
);
147 return ((ticks
== 0) ? 1 : ticks
);
150 int kstat_copy(const kstat_t
*src
, kstat_t
*dst
)
152 void *dst_data
= NULL
;
154 if (dst
->ks_data
&& dst
->ks_data_size
< src
->ks_data_size
)
155 free((void *)dst
->ks_data
);
157 dst_data
= dst
->ks_data
;
161 if (src
->ks_data
!= NULL
) {
163 dst
->ks_data
= dst_data
;
164 else if ((dst
->ks_data
= malloc(src
->ks_data_size
)) == NULL
)
166 bcopy(src
->ks_data
, dst
->ks_data
, src
->ks_data_size
);
169 free((void *)dst_data
);
171 dst
->ks_data_size
= 0;
176 /* Get_CPU_Load returns an array of CPU loads, one for each CPU, scaled
177 to HAUTEUR. The array is defined and allocated by the main program
178 and passed to the function as '*load'. The number of CPUs present
179 is given in 'Cpu_tot' */
180 unsigned int *Get_CPU_Load(unsigned int *load
, unsigned int Cpu_tot
)
187 if (kcp
== NULL
|| ksp_old
== NULL
)
190 for (i
= 0; i
< Cpu_tot
; i
++) {
191 if ((ksp_new
= kstat_lookup(kcp
, "cpu", i
, "sys")) == NULL
) {
196 if (kstat_read(kcp
, ksp_new
, NULL
) == -1) {
201 cur_load
= cpu_ticks_delta(&ksp_old
[i
], ksp_new
);
202 factor
= HAUTEUR
/ (double)cur_load
;
204 cur_load
= kstat_delta(&ksp_old
[i
], ksp_new
,
205 cpu_states
[1].field_name
, &cpu_states
[1].index
) +
206 kstat_delta(&ksp_old
[i
], ksp_new
, cpu_states
[2].field_name
,
207 &cpu_states
[2].index
);
208 if (ksp_old
[i
].ks_data
) {
209 load
[i
] = factor
* cur_load
;
211 kstat_copy(ksp_new
, &ksp_old
[i
]);
217 /* return current memory/swap usage on a scale from 0-100 */
218 unsigned int Get_Memory(void)
221 static vminfo_t
*vm_new
= NULL
;
222 static vminfo_t
*vm_old
= NULL
;
224 static uint64_t freemem
= 0;
226 if ((ksp_new
= kstat_lookup(kcp
, "unix", 0, "vminfo")) == NULL
) {
230 if (vm_new
== NULL
&& (vm_new
= malloc(sizeof (vminfo_t
))) == NULL
) {
234 if (kstat_read(kcp
, ksp_new
, vm_new
) == -1) {
238 if (vm_old
!= NULL
) {
239 uint64_t step
= vm_new
->updates
- vm_old
->updates
;
242 freemem
= (vm_new
->freemem
- vm_old
->freemem
) / step
;
253 return (100 * (physmem
- freemem
) / physmem
);
256 unsigned int Get_Swap(void)
260 if (swapctl(SC_AINFO
, &ai
) == -1) {
264 return (100 * (ai
.ani_max
- ai
.ani_free
) / ai
.ani_max
);