Print this page
3900 illumos will not build against gcc compiled perl
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs
+++ new/usr/src/cmd/perl/contrib/Sun/Solaris/Kstat/Kstat.xs
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2014 Racktop Systems.
24 25 */
25 26
26 27 /*
27 28 * Kstat.xs is a Perl XS (eXStension module) that makes the Solaris
28 29 * kstat(3KSTAT) facility available to Perl scripts. Kstat is a general-purpose
29 30 * mechanism for providing kernel statistics to users. The Solaris API is
30 31 * function-based (see the manpage for details), but for ease of use in Perl
31 32 * scripts this module presents the information as a nested hash data structure.
32 33 * It would be too inefficient to read every kstat in the system, so this module
33 34 * uses the Perl TIEHASH mechanism to implement a read-on-demand semantic, which
34 35 * only reads and updates kstats as and when they are actually accessed.
35 36 */
36 37
37 38 /*
38 39 * Ignored raw kstats.
39 40 *
40 41 * Some raw kstats are ignored by this module, these are listed below. The
41 42 * most common reason is that the kstats are stored as arrays and the ks_ndata
42 43 * and/or ks_data_size fields are invalid. In this case it is impossible to
43 44 * know how many records are in the array, so they can't be read.
44 45 *
45 46 * unix:*:sfmmu_percpu_stat
46 47 * This is stored as an array with one entry per cpu. Each element is of type
47 48 * struct sfmmu_percpu_stat. The ks_ndata and ks_data_size fields are bogus.
48 49 *
49 50 * ufs directio:*:UFS DirectIO Stats
50 51 * The structure definition used for these kstats (ufs_directio_kstats) is in a
51 52 * C file (uts/common/fs/ufs/ufs_directio.c) rather than a header file, so it
52 53 * isn't accessible.
53 54 *
54 55 * qlc:*:statistics
55 56 * This is a third-party driver for which we don't have source.
56 57 *
57 58 * mm:*:phys_installed
58 59 * This is stored as an array of uint64_t, with each pair of values being the
59 60 * (address, size) of a memory segment. The ks_ndata and ks_data_size fields
60 61 * are both zero.
61 62 *
62 63 * sockfs:*:sock_unix_list
63 64 * This is stored as an array with one entry per active socket. Each element
64 65 * is of type struct k_sockinfo. The ks_ndata and ks_data_size fields are both
65 66 * zero.
66 67 *
67 68 * Note that the ks_ndata and ks_data_size of many non-array raw kstats are
68 69 * also incorrect. The relevant assertions are therefore commented out in the
69 70 * appropriate raw kstat read routines.
70 71 */
71 72
72 73 /* Kstat related includes */
73 74 #include <libgen.h>
74 75 #include <kstat.h>
75 76 #include <sys/var.h>
76 77 #include <sys/utsname.h>
77 78 #include <sys/sysinfo.h>
78 79 #include <sys/flock.h>
79 80 #include <sys/dnlc.h>
80 81 #include <nfs/nfs.h>
81 82 #include <nfs/nfs_clnt.h>
82 83
83 84 /* Ultra-specific kstat includes */
84 85 #ifdef __sparc
85 86 #include <vm/hat_sfmmu.h> /* from /usr/platform/sun4u/include */
86 87 #include <sys/simmstat.h> /* from /usr/platform/sun4u/include */
87 88 #include <sys/sysctrl.h> /* from /usr/platform/sun4u/include */
88 89 #include <sys/fhc.h> /* from /usr/include */
89 90 #endif
90 91
91 92 /*
92 93 * Solaris #defines SP, which conflicts with the perl definition of SP
93 94 * We don't need the Solaris one, so get rid of it to avoid warnings
94 95 */
95 96 #undef SP
96 97
97 98 /* Perl XS includes */
98 99 #include "EXTERN.h"
99 100 #include "perl.h"
100 101 #include "XSUB.h"
101 102
102 103 /* Debug macros */
103 104 #define DEBUG_ID "Sun::Solaris::Kstat"
104 105 #ifdef KSTAT_DEBUG
105 106 #define PERL_ASSERT(EXP) \
106 107 ((void)((EXP) || (croak("%s: assertion failed at %s:%d: %s", \
107 108 DEBUG_ID, __FILE__, __LINE__, #EXP), 0), 0))
108 109 #define PERL_ASSERTMSG(EXP, MSG) \
109 110 ((void)((EXP) || (croak(DEBUG_ID ": " MSG), 0), 0))
110 111 #else
111 112 #define PERL_ASSERT(EXP) ((void)0)
112 113 #define PERL_ASSERTMSG(EXP, MSG) ((void)0)
113 114 #endif
114 115
115 116 /* Macros for saving the contents of KSTAT_RAW structures */
116 117 #if defined(HAS_QUAD) && defined(USE_64_BIT_INT)
117 118 #define NEW_IV(V) \
118 119 (newSViv((IVTYPE) V))
119 120 #define NEW_UV(V) \
120 121 (newSVuv((UVTYPE) V))
121 122 #else
122 123 #define NEW_IV(V) \
123 124 (V >= IV_MIN && V <= IV_MAX ? newSViv((IVTYPE) V) : newSVnv((NVTYPE) V))
124 125 #if defined(UVTYPE)
125 126 #define NEW_UV(V) \
126 127 (V <= UV_MAX ? newSVuv((UVTYPE) V) : newSVnv((NVTYPE) V))
127 128 # else
128 129 #define NEW_UV(V) \
129 130 (V <= IV_MAX ? newSViv((IVTYPE) V) : newSVnv((NVTYPE) V))
130 131 #endif
131 132 #endif
132 133 #define NEW_HRTIME(V) \
133 134 newSVnv((NVTYPE) (V / 1000000000.0))
134 135
135 136 #define SAVE_FNP(H, F, K) \
136 137 hv_store(H, K, sizeof (K) - 1, newSViv((IVTYPE)(uintptr_t)&F), 0)
137 138 #define SAVE_STRING(H, S, K, SS) \
138 139 hv_store(H, #K, sizeof (#K) - 1, \
139 140 newSVpvn(S->K, SS ? strlen(S->K) : sizeof(S->K)), 0)
140 141 #define SAVE_INT32(H, S, K) \
141 142 hv_store(H, #K, sizeof (#K) - 1, NEW_IV(S->K), 0)
142 143 #define SAVE_UINT32(H, S, K) \
143 144 hv_store(H, #K, sizeof (#K) - 1, NEW_UV(S->K), 0)
144 145 #define SAVE_INT64(H, S, K) \
145 146 hv_store(H, #K, sizeof (#K) - 1, NEW_IV(S->K), 0)
146 147 #define SAVE_UINT64(H, S, K) \
147 148 hv_store(H, #K, sizeof (#K) - 1, NEW_UV(S->K), 0)
148 149 #define SAVE_HRTIME(H, S, K) \
149 150 hv_store(H, #K, sizeof (#K) - 1, NEW_HRTIME(S->K), 0)
150 151
151 152 /* Private structure used for saving kstat info in the tied hashes */
152 153 typedef struct {
153 154 char read; /* Kstat block has been read before */
154 155 char valid; /* Kstat still exists in kstat chain */
155 156 char strip_str; /* Strip KSTAT_DATA_CHAR fields */
156 157 kstat_ctl_t *kstat_ctl; /* Handle returned by kstat_open */
157 158 kstat_t *kstat; /* Handle used by kstat_read */
158 159 } KstatInfo_t;
159 160
160 161 /* typedef for apply_to_ties callback functions */
161 162 typedef int (*ATTCb_t)(HV *, void *);
162 163
163 164 /* typedef for raw kstat reader functions */
164 165 typedef void (*kstat_raw_reader_t)(HV *, kstat_t *, int);
165 166
166 167 /* Hash of "module:name" to KSTAT_RAW read functions */
167 168 static HV *raw_kstat_lookup;
168 169
169 170 /*
170 171 * Kstats come in two flavours, named and raw. Raw kstats are just C structs,
171 172 * so we need a function per raw kstat to convert the C struct into the
172 173 * corresponding perl hash. All such conversion functions are in the following
173 174 * section.
174 175 */
175 176
176 177 /*
177 178 * Definitions in /usr/include/sys/cpuvar.h and /usr/include/sys/sysinfo.h
178 179 */
179 180
180 181 static void
181 182 save_cpu_stat(HV *self, kstat_t *kp, int strip_str)
182 183 {
183 184 cpu_stat_t *statp;
184 185 cpu_sysinfo_t *sysinfop;
185 186 cpu_syswait_t *syswaitp;
186 187 cpu_vminfo_t *vminfop;
187 188
188 189 /* PERL_ASSERT(kp->ks_ndata == 1); */
189 190 PERL_ASSERT(kp->ks_data_size == sizeof (cpu_stat_t));
190 191 statp = (cpu_stat_t *)(kp->ks_data);
191 192 sysinfop = &statp->cpu_sysinfo;
192 193 syswaitp = &statp->cpu_syswait;
193 194 vminfop = &statp->cpu_vminfo;
194 195
195 196 hv_store(self, "idle", 4, NEW_UV(sysinfop->cpu[CPU_IDLE]), 0);
196 197 hv_store(self, "user", 4, NEW_UV(sysinfop->cpu[CPU_USER]), 0);
197 198 hv_store(self, "kernel", 6, NEW_UV(sysinfop->cpu[CPU_KERNEL]), 0);
198 199 hv_store(self, "wait", 4, NEW_UV(sysinfop->cpu[CPU_WAIT]), 0);
199 200 hv_store(self, "wait_io", 7, NEW_UV(sysinfop->wait[W_IO]), 0);
200 201 hv_store(self, "wait_swap", 9, NEW_UV(sysinfop->wait[W_SWAP]), 0);
201 202 hv_store(self, "wait_pio", 8, NEW_UV(sysinfop->wait[W_PIO]), 0);
202 203 SAVE_UINT32(self, sysinfop, bread);
203 204 SAVE_UINT32(self, sysinfop, bwrite);
204 205 SAVE_UINT32(self, sysinfop, lread);
205 206 SAVE_UINT32(self, sysinfop, lwrite);
206 207 SAVE_UINT32(self, sysinfop, phread);
207 208 SAVE_UINT32(self, sysinfop, phwrite);
208 209 SAVE_UINT32(self, sysinfop, pswitch);
209 210 SAVE_UINT32(self, sysinfop, trap);
210 211 SAVE_UINT32(self, sysinfop, intr);
211 212 SAVE_UINT32(self, sysinfop, syscall);
212 213 SAVE_UINT32(self, sysinfop, sysread);
213 214 SAVE_UINT32(self, sysinfop, syswrite);
214 215 SAVE_UINT32(self, sysinfop, sysfork);
215 216 SAVE_UINT32(self, sysinfop, sysvfork);
216 217 SAVE_UINT32(self, sysinfop, sysexec);
217 218 SAVE_UINT32(self, sysinfop, readch);
218 219 SAVE_UINT32(self, sysinfop, writech);
219 220 SAVE_UINT32(self, sysinfop, rcvint);
220 221 SAVE_UINT32(self, sysinfop, xmtint);
221 222 SAVE_UINT32(self, sysinfop, mdmint);
222 223 SAVE_UINT32(self, sysinfop, rawch);
223 224 SAVE_UINT32(self, sysinfop, canch);
224 225 SAVE_UINT32(self, sysinfop, outch);
225 226 SAVE_UINT32(self, sysinfop, msg);
226 227 SAVE_UINT32(self, sysinfop, sema);
227 228 SAVE_UINT32(self, sysinfop, namei);
228 229 SAVE_UINT32(self, sysinfop, ufsiget);
229 230 SAVE_UINT32(self, sysinfop, ufsdirblk);
230 231 SAVE_UINT32(self, sysinfop, ufsipage);
231 232 SAVE_UINT32(self, sysinfop, ufsinopage);
232 233 SAVE_UINT32(self, sysinfop, inodeovf);
233 234 SAVE_UINT32(self, sysinfop, fileovf);
234 235 SAVE_UINT32(self, sysinfop, procovf);
235 236 SAVE_UINT32(self, sysinfop, intrthread);
236 237 SAVE_UINT32(self, sysinfop, intrblk);
237 238 SAVE_UINT32(self, sysinfop, idlethread);
238 239 SAVE_UINT32(self, sysinfop, inv_swtch);
239 240 SAVE_UINT32(self, sysinfop, nthreads);
240 241 SAVE_UINT32(self, sysinfop, cpumigrate);
241 242 SAVE_UINT32(self, sysinfop, xcalls);
242 243 SAVE_UINT32(self, sysinfop, mutex_adenters);
243 244 SAVE_UINT32(self, sysinfop, rw_rdfails);
244 245 SAVE_UINT32(self, sysinfop, rw_wrfails);
245 246 SAVE_UINT32(self, sysinfop, modload);
246 247 SAVE_UINT32(self, sysinfop, modunload);
247 248 SAVE_UINT32(self, sysinfop, bawrite);
248 249 #ifdef STATISTICS /* see header file */
249 250 SAVE_UINT32(self, sysinfop, rw_enters);
250 251 SAVE_UINT32(self, sysinfop, win_uo_cnt);
251 252 SAVE_UINT32(self, sysinfop, win_uu_cnt);
252 253 SAVE_UINT32(self, sysinfop, win_so_cnt);
253 254 SAVE_UINT32(self, sysinfop, win_su_cnt);
254 255 SAVE_UINT32(self, sysinfop, win_suo_cnt);
255 256 #endif
256 257
257 258 SAVE_INT32(self, syswaitp, iowait);
258 259 SAVE_INT32(self, syswaitp, swap);
259 260 SAVE_INT32(self, syswaitp, physio);
260 261
261 262 SAVE_UINT32(self, vminfop, pgrec);
262 263 SAVE_UINT32(self, vminfop, pgfrec);
263 264 SAVE_UINT32(self, vminfop, pgin);
264 265 SAVE_UINT32(self, vminfop, pgpgin);
265 266 SAVE_UINT32(self, vminfop, pgout);
266 267 SAVE_UINT32(self, vminfop, pgpgout);
267 268 SAVE_UINT32(self, vminfop, swapin);
268 269 SAVE_UINT32(self, vminfop, pgswapin);
269 270 SAVE_UINT32(self, vminfop, swapout);
270 271 SAVE_UINT32(self, vminfop, pgswapout);
271 272 SAVE_UINT32(self, vminfop, zfod);
272 273 SAVE_UINT32(self, vminfop, dfree);
273 274 SAVE_UINT32(self, vminfop, scan);
274 275 SAVE_UINT32(self, vminfop, rev);
275 276 SAVE_UINT32(self, vminfop, hat_fault);
276 277 SAVE_UINT32(self, vminfop, as_fault);
277 278 SAVE_UINT32(self, vminfop, maj_fault);
278 279 SAVE_UINT32(self, vminfop, cow_fault);
279 280 SAVE_UINT32(self, vminfop, prot_fault);
280 281 SAVE_UINT32(self, vminfop, softlock);
281 282 SAVE_UINT32(self, vminfop, kernel_asflt);
282 283 SAVE_UINT32(self, vminfop, pgrrun);
283 284 SAVE_UINT32(self, vminfop, execpgin);
284 285 SAVE_UINT32(self, vminfop, execpgout);
285 286 SAVE_UINT32(self, vminfop, execfree);
286 287 SAVE_UINT32(self, vminfop, anonpgin);
287 288 SAVE_UINT32(self, vminfop, anonpgout);
288 289 SAVE_UINT32(self, vminfop, anonfree);
289 290 SAVE_UINT32(self, vminfop, fspgin);
290 291 SAVE_UINT32(self, vminfop, fspgout);
291 292 SAVE_UINT32(self, vminfop, fsfree);
292 293 }
293 294
294 295 /*
295 296 * Definitions in /usr/include/sys/var.h
296 297 */
297 298
298 299 static void
299 300 save_var(HV *self, kstat_t *kp, int strip_str)
300 301 {
301 302 struct var *varp;
302 303
303 304 /* PERL_ASSERT(kp->ks_ndata == 1); */
304 305 PERL_ASSERT(kp->ks_data_size == sizeof (struct var));
305 306 varp = (struct var *)(kp->ks_data);
306 307
307 308 SAVE_INT32(self, varp, v_buf);
308 309 SAVE_INT32(self, varp, v_call);
309 310 SAVE_INT32(self, varp, v_proc);
310 311 SAVE_INT32(self, varp, v_maxupttl);
311 312 SAVE_INT32(self, varp, v_nglobpris);
312 313 SAVE_INT32(self, varp, v_maxsyspri);
313 314 SAVE_INT32(self, varp, v_clist);
314 315 SAVE_INT32(self, varp, v_maxup);
315 316 SAVE_INT32(self, varp, v_hbuf);
316 317 SAVE_INT32(self, varp, v_hmask);
317 318 SAVE_INT32(self, varp, v_pbuf);
318 319 SAVE_INT32(self, varp, v_sptmap);
319 320 SAVE_INT32(self, varp, v_maxpmem);
320 321 SAVE_INT32(self, varp, v_autoup);
321 322 SAVE_INT32(self, varp, v_bufhwm);
322 323 }
323 324
324 325 /*
325 326 * Definition in /usr/include/sys/dnlc.h
326 327 */
327 328
328 329 static void
329 330 save_ncstats(HV *self, kstat_t *kp, int strip_str)
330 331 {
331 332 struct ncstats *ncstatsp;
332 333
333 334 /* PERL_ASSERT(kp->ks_ndata == 1); */
334 335 PERL_ASSERT(kp->ks_data_size == sizeof (struct ncstats));
335 336 ncstatsp = (struct ncstats *)(kp->ks_data);
336 337
337 338 SAVE_INT32(self, ncstatsp, hits);
338 339 SAVE_INT32(self, ncstatsp, misses);
339 340 SAVE_INT32(self, ncstatsp, enters);
340 341 SAVE_INT32(self, ncstatsp, dbl_enters);
341 342 SAVE_INT32(self, ncstatsp, long_enter);
342 343 SAVE_INT32(self, ncstatsp, long_look);
343 344 SAVE_INT32(self, ncstatsp, move_to_front);
344 345 SAVE_INT32(self, ncstatsp, purges);
345 346 }
346 347
347 348 /*
348 349 * Definition in /usr/include/sys/sysinfo.h
349 350 */
350 351
351 352 static void
352 353 save_sysinfo(HV *self, kstat_t *kp, int strip_str)
353 354 {
354 355 sysinfo_t *sysinfop;
355 356
356 357 /* PERL_ASSERT(kp->ks_ndata == 1); */
357 358 PERL_ASSERT(kp->ks_data_size == sizeof (sysinfo_t));
358 359 sysinfop = (sysinfo_t *)(kp->ks_data);
359 360
360 361 SAVE_UINT32(self, sysinfop, updates);
361 362 SAVE_UINT32(self, sysinfop, runque);
362 363 SAVE_UINT32(self, sysinfop, runocc);
363 364 SAVE_UINT32(self, sysinfop, swpque);
364 365 SAVE_UINT32(self, sysinfop, swpocc);
365 366 SAVE_UINT32(self, sysinfop, waiting);
366 367 }
367 368
368 369 /*
369 370 * Definition in /usr/include/sys/sysinfo.h
370 371 */
371 372
372 373 static void
373 374 save_vminfo(HV *self, kstat_t *kp, int strip_str)
374 375 {
375 376 vminfo_t *vminfop;
376 377
377 378 /* PERL_ASSERT(kp->ks_ndata == 1); */
378 379 PERL_ASSERT(kp->ks_data_size == sizeof (vminfo_t));
379 380 vminfop = (vminfo_t *)(kp->ks_data);
380 381
381 382 SAVE_UINT64(self, vminfop, freemem);
382 383 SAVE_UINT64(self, vminfop, swap_resv);
383 384 SAVE_UINT64(self, vminfop, swap_alloc);
384 385 SAVE_UINT64(self, vminfop, swap_avail);
385 386 SAVE_UINT64(self, vminfop, swap_free);
386 387 SAVE_UINT64(self, vminfop, updates);
387 388 }
388 389
389 390 /*
390 391 * Definition in /usr/include/nfs/nfs_clnt.h
391 392 */
392 393
393 394 static void
394 395 save_nfs(HV *self, kstat_t *kp, int strip_str)
395 396 {
396 397 struct mntinfo_kstat *mntinfop;
397 398
398 399 /* PERL_ASSERT(kp->ks_ndata == 1); */
399 400 PERL_ASSERT(kp->ks_data_size == sizeof (struct mntinfo_kstat));
400 401 mntinfop = (struct mntinfo_kstat *)(kp->ks_data);
401 402
402 403 SAVE_STRING(self, mntinfop, mik_proto, strip_str);
403 404 SAVE_UINT32(self, mntinfop, mik_vers);
404 405 SAVE_UINT32(self, mntinfop, mik_flags);
405 406 SAVE_UINT32(self, mntinfop, mik_secmod);
406 407 SAVE_UINT32(self, mntinfop, mik_curread);
407 408 SAVE_UINT32(self, mntinfop, mik_curwrite);
408 409 SAVE_INT32(self, mntinfop, mik_timeo);
409 410 SAVE_INT32(self, mntinfop, mik_retrans);
410 411 SAVE_UINT32(self, mntinfop, mik_acregmin);
411 412 SAVE_UINT32(self, mntinfop, mik_acregmax);
412 413 SAVE_UINT32(self, mntinfop, mik_acdirmin);
413 414 SAVE_UINT32(self, mntinfop, mik_acdirmax);
414 415 hv_store(self, "lookup_srtt", 11,
415 416 NEW_UV(mntinfop->mik_timers[0].srtt), 0);
416 417 hv_store(self, "lookup_deviate", 14,
417 418 NEW_UV(mntinfop->mik_timers[0].deviate), 0);
418 419 hv_store(self, "lookup_rtxcur", 13,
419 420 NEW_UV(mntinfop->mik_timers[0].rtxcur), 0);
420 421 hv_store(self, "read_srtt", 9,
421 422 NEW_UV(mntinfop->mik_timers[1].srtt), 0);
422 423 hv_store(self, "read_deviate", 12,
423 424 NEW_UV(mntinfop->mik_timers[1].deviate), 0);
424 425 hv_store(self, "read_rtxcur", 11,
425 426 NEW_UV(mntinfop->mik_timers[1].rtxcur), 0);
426 427 hv_store(self, "write_srtt", 10,
427 428 NEW_UV(mntinfop->mik_timers[2].srtt), 0);
428 429 hv_store(self, "write_deviate", 13,
429 430 NEW_UV(mntinfop->mik_timers[2].deviate), 0);
430 431 hv_store(self, "write_rtxcur", 12,
431 432 NEW_UV(mntinfop->mik_timers[2].rtxcur), 0);
432 433 SAVE_UINT32(self, mntinfop, mik_noresponse);
433 434 SAVE_UINT32(self, mntinfop, mik_failover);
434 435 SAVE_UINT32(self, mntinfop, mik_remap);
435 436 SAVE_STRING(self, mntinfop, mik_curserver, strip_str);
436 437 }
437 438
438 439 /*
439 440 * The following struct => hash functions are all only present on the sparc
440 441 * platform, so they are all conditionally compiled depending on __sparc
441 442 */
442 443
443 444 /*
444 445 * Definition in /usr/platform/sun4u/include/vm/hat_sfmmu.h
445 446 */
446 447
447 448 #ifdef __sparc
448 449 static void
449 450 save_sfmmu_global_stat(HV *self, kstat_t *kp, int strip_str)
450 451 {
451 452 struct sfmmu_global_stat *sfmmugp;
452 453
453 454 /* PERL_ASSERT(kp->ks_ndata == 1); */
454 455 PERL_ASSERT(kp->ks_data_size == sizeof (struct sfmmu_global_stat));
455 456 sfmmugp = (struct sfmmu_global_stat *)(kp->ks_data);
456 457
457 458 SAVE_INT32(self, sfmmugp, sf_tsb_exceptions);
458 459 SAVE_INT32(self, sfmmugp, sf_tsb_raise_exception);
459 460 SAVE_INT32(self, sfmmugp, sf_pagefaults);
460 461 SAVE_INT32(self, sfmmugp, sf_uhash_searches);
461 462 SAVE_INT32(self, sfmmugp, sf_uhash_links);
462 463 SAVE_INT32(self, sfmmugp, sf_khash_searches);
463 464 SAVE_INT32(self, sfmmugp, sf_khash_links);
464 465 SAVE_INT32(self, sfmmugp, sf_swapout);
465 466 SAVE_INT32(self, sfmmugp, sf_tsb_alloc);
466 467 SAVE_INT32(self, sfmmugp, sf_tsb_allocfail);
467 468 SAVE_INT32(self, sfmmugp, sf_tsb_sectsb_create);
468 469 SAVE_INT32(self, sfmmugp, sf_scd_1sttsb_alloc);
469 470 SAVE_INT32(self, sfmmugp, sf_scd_2ndtsb_alloc);
470 471 SAVE_INT32(self, sfmmugp, sf_scd_1sttsb_allocfail);
471 472 SAVE_INT32(self, sfmmugp, sf_scd_2ndtsb_allocfail);
472 473 SAVE_INT32(self, sfmmugp, sf_tteload8k);
473 474 SAVE_INT32(self, sfmmugp, sf_tteload64k);
474 475 SAVE_INT32(self, sfmmugp, sf_tteload512k);
475 476 SAVE_INT32(self, sfmmugp, sf_tteload4m);
476 477 SAVE_INT32(self, sfmmugp, sf_tteload32m);
477 478 SAVE_INT32(self, sfmmugp, sf_tteload256m);
478 479 SAVE_INT32(self, sfmmugp, sf_tsb_load8k);
479 480 SAVE_INT32(self, sfmmugp, sf_tsb_load4m);
480 481 SAVE_INT32(self, sfmmugp, sf_hblk_hit);
481 482 SAVE_INT32(self, sfmmugp, sf_hblk8_ncreate);
482 483 SAVE_INT32(self, sfmmugp, sf_hblk8_nalloc);
483 484 SAVE_INT32(self, sfmmugp, sf_hblk1_ncreate);
484 485 SAVE_INT32(self, sfmmugp, sf_hblk1_nalloc);
485 486 SAVE_INT32(self, sfmmugp, sf_hblk_slab_cnt);
486 487 SAVE_INT32(self, sfmmugp, sf_hblk_reserve_cnt);
487 488 SAVE_INT32(self, sfmmugp, sf_hblk_recurse_cnt);
488 489 SAVE_INT32(self, sfmmugp, sf_hblk_reserve_hit);
489 490 SAVE_INT32(self, sfmmugp, sf_get_free_success);
490 491 SAVE_INT32(self, sfmmugp, sf_get_free_throttle);
491 492 SAVE_INT32(self, sfmmugp, sf_get_free_fail);
492 493 SAVE_INT32(self, sfmmugp, sf_put_free_success);
493 494 SAVE_INT32(self, sfmmugp, sf_put_free_fail);
494 495 SAVE_INT32(self, sfmmugp, sf_pgcolor_conflict);
495 496 SAVE_INT32(self, sfmmugp, sf_uncache_conflict);
496 497 SAVE_INT32(self, sfmmugp, sf_unload_conflict);
497 498 SAVE_INT32(self, sfmmugp, sf_ism_uncache);
498 499 SAVE_INT32(self, sfmmugp, sf_ism_recache);
499 500 SAVE_INT32(self, sfmmugp, sf_recache);
500 501 SAVE_INT32(self, sfmmugp, sf_steal_count);
501 502 SAVE_INT32(self, sfmmugp, sf_pagesync);
502 503 SAVE_INT32(self, sfmmugp, sf_clrwrt);
503 504 SAVE_INT32(self, sfmmugp, sf_pagesync_invalid);
504 505 SAVE_INT32(self, sfmmugp, sf_kernel_xcalls);
505 506 SAVE_INT32(self, sfmmugp, sf_user_xcalls);
506 507 SAVE_INT32(self, sfmmugp, sf_tsb_grow);
507 508 SAVE_INT32(self, sfmmugp, sf_tsb_shrink);
508 509 SAVE_INT32(self, sfmmugp, sf_tsb_resize_failures);
509 510 SAVE_INT32(self, sfmmugp, sf_tsb_reloc);
510 511 SAVE_INT32(self, sfmmugp, sf_user_vtop);
511 512 SAVE_INT32(self, sfmmugp, sf_ctx_inv);
512 513 SAVE_INT32(self, sfmmugp, sf_tlb_reprog_pgsz);
513 514 SAVE_INT32(self, sfmmugp, sf_region_remap_demap);
514 515 SAVE_INT32(self, sfmmugp, sf_create_scd);
515 516 SAVE_INT32(self, sfmmugp, sf_join_scd);
516 517 SAVE_INT32(self, sfmmugp, sf_leave_scd);
517 518 SAVE_INT32(self, sfmmugp, sf_destroy_scd);
518 519 }
519 520 #endif
520 521
521 522 /*
522 523 * Definition in /usr/platform/sun4u/include/vm/hat_sfmmu.h
523 524 */
524 525
525 526 #ifdef __sparc
526 527 static void
527 528 save_sfmmu_tsbsize_stat(HV *self, kstat_t *kp, int strip_str)
528 529 {
529 530 struct sfmmu_tsbsize_stat *sfmmutp;
530 531
531 532 /* PERL_ASSERT(kp->ks_ndata == 1); */
532 533 PERL_ASSERT(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat));
533 534 sfmmutp = (struct sfmmu_tsbsize_stat *)(kp->ks_data);
534 535
535 536 SAVE_INT32(self, sfmmutp, sf_tsbsz_8k);
536 537 SAVE_INT32(self, sfmmutp, sf_tsbsz_16k);
537 538 SAVE_INT32(self, sfmmutp, sf_tsbsz_32k);
538 539 SAVE_INT32(self, sfmmutp, sf_tsbsz_64k);
539 540 SAVE_INT32(self, sfmmutp, sf_tsbsz_128k);
540 541 SAVE_INT32(self, sfmmutp, sf_tsbsz_256k);
541 542 SAVE_INT32(self, sfmmutp, sf_tsbsz_512k);
542 543 SAVE_INT32(self, sfmmutp, sf_tsbsz_1m);
543 544 SAVE_INT32(self, sfmmutp, sf_tsbsz_2m);
544 545 SAVE_INT32(self, sfmmutp, sf_tsbsz_4m);
545 546 }
546 547 #endif
547 548
548 549 /*
549 550 * Definition in /usr/platform/sun4u/include/sys/simmstat.h
550 551 */
551 552
552 553 #ifdef __sparc
553 554 static void
554 555 save_simmstat(HV *self, kstat_t *kp, int strip_str)
555 556 {
556 557 uchar_t *simmstatp;
557 558 SV *list;
558 559 int i;
559 560
560 561 /* PERL_ASSERT(kp->ks_ndata == 1); */
561 562 PERL_ASSERT(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT);
562 563
563 564 list = newSVpv("", 0);
564 565 for (i = 0, simmstatp = (uchar_t *)(kp->ks_data);
565 566 i < SIMM_COUNT - 1; i++, simmstatp++) {
566 567 sv_catpvf(list, "%d,", *simmstatp);
567 568 }
568 569 sv_catpvf(list, "%d", *simmstatp);
569 570 hv_store(self, "status", 6, list, 0);
570 571 }
571 572 #endif
572 573
573 574 /*
574 575 * Used by save_temperature to make CSV lists from arrays of
575 576 * short temperature values
576 577 */
577 578
578 579 #ifdef __sparc
579 580 static SV *
580 581 short_array_to_SV(short *shortp, int len)
581 582 {
582 583 SV *list;
583 584
584 585 list = newSVpv("", 0);
585 586 for (; len > 1; len--, shortp++) {
586 587 sv_catpvf(list, "%d,", *shortp);
587 588 }
588 589 sv_catpvf(list, "%d", *shortp);
589 590 return (list);
590 591 }
591 592
592 593 /*
593 594 * Definition in /usr/platform/sun4u/include/sys/fhc.h
594 595 */
595 596
596 597 static void
597 598 save_temperature(HV *self, kstat_t *kp, int strip_str)
598 599 {
599 600 struct temp_stats *tempsp;
600 601
601 602 /* PERL_ASSERT(kp->ks_ndata == 1); */
602 603 PERL_ASSERT(kp->ks_data_size == sizeof (struct temp_stats));
603 604 tempsp = (struct temp_stats *)(kp->ks_data);
604 605
605 606 SAVE_UINT32(self, tempsp, index);
606 607 hv_store(self, "l1", 2, short_array_to_SV(tempsp->l1, L1_SZ), 0);
607 608 hv_store(self, "l2", 2, short_array_to_SV(tempsp->l2, L2_SZ), 0);
608 609 hv_store(self, "l3", 2, short_array_to_SV(tempsp->l3, L3_SZ), 0);
609 610 hv_store(self, "l4", 2, short_array_to_SV(tempsp->l4, L4_SZ), 0);
610 611 hv_store(self, "l5", 2, short_array_to_SV(tempsp->l5, L5_SZ), 0);
611 612 SAVE_INT32(self, tempsp, max);
612 613 SAVE_INT32(self, tempsp, min);
613 614 SAVE_INT32(self, tempsp, state);
614 615 SAVE_INT32(self, tempsp, temp_cnt);
615 616 SAVE_INT32(self, tempsp, shutdown_cnt);
616 617 SAVE_INT32(self, tempsp, version);
617 618 SAVE_INT32(self, tempsp, trend);
618 619 SAVE_INT32(self, tempsp, override);
619 620 }
620 621 #endif
621 622
622 623 /*
623 624 * Not actually defined anywhere - just a short. Yuck.
624 625 */
625 626
626 627 #ifdef __sparc
627 628 static void
628 629 save_temp_over(HV *self, kstat_t *kp, int strip_str)
629 630 {
630 631 short *shortp;
631 632
632 633 /* PERL_ASSERT(kp->ks_ndata == 1); */
633 634 PERL_ASSERT(kp->ks_data_size == sizeof (short));
634 635
635 636 shortp = (short *)(kp->ks_data);
636 637 hv_store(self, "override", 8, newSViv(*shortp), 0);
637 638 }
638 639 #endif
639 640
640 641 /*
641 642 * Defined in /usr/platform/sun4u/include/sys/sysctrl.h
642 643 * (Well, sort of. Actually there's no structure, just a list of #defines
643 644 * enumerating *some* of the array indexes.)
644 645 */
645 646
646 647 #ifdef __sparc
647 648 static void
648 649 save_ps_shadow(HV *self, kstat_t *kp, int strip_str)
649 650 {
650 651 uchar_t *ucharp;
651 652
652 653 /* PERL_ASSERT(kp->ks_ndata == 1); */
653 654 PERL_ASSERT(kp->ks_data_size == SYS_PS_COUNT);
654 655
655 656 ucharp = (uchar_t *)(kp->ks_data);
656 657 hv_store(self, "core_0", 6, newSViv(*ucharp++), 0);
657 658 hv_store(self, "core_1", 6, newSViv(*ucharp++), 0);
658 659 hv_store(self, "core_2", 6, newSViv(*ucharp++), 0);
659 660 hv_store(self, "core_3", 6, newSViv(*ucharp++), 0);
660 661 hv_store(self, "core_4", 6, newSViv(*ucharp++), 0);
661 662 hv_store(self, "core_5", 6, newSViv(*ucharp++), 0);
662 663 hv_store(self, "core_6", 6, newSViv(*ucharp++), 0);
663 664 hv_store(self, "core_7", 6, newSViv(*ucharp++), 0);
664 665 hv_store(self, "pps_0", 5, newSViv(*ucharp++), 0);
665 666 hv_store(self, "clk_33", 6, newSViv(*ucharp++), 0);
666 667 hv_store(self, "clk_50", 6, newSViv(*ucharp++), 0);
667 668 hv_store(self, "v5_p", 4, newSViv(*ucharp++), 0);
668 669 hv_store(self, "v12_p", 5, newSViv(*ucharp++), 0);
669 670 hv_store(self, "v5_aux", 6, newSViv(*ucharp++), 0);
670 671 hv_store(self, "v5_p_pch", 8, newSViv(*ucharp++), 0);
671 672 hv_store(self, "v12_p_pch", 9, newSViv(*ucharp++), 0);
672 673 hv_store(self, "v3_pch", 6, newSViv(*ucharp++), 0);
673 674 hv_store(self, "v5_pch", 6, newSViv(*ucharp++), 0);
674 675 hv_store(self, "p_fan", 5, newSViv(*ucharp++), 0);
675 676 }
676 677 #endif
677 678
678 679 /*
679 680 * Definition in /usr/platform/sun4u/include/sys/fhc.h
680 681 */
681 682
682 683 #ifdef __sparc
683 684 static void
684 685 save_fault_list(HV *self, kstat_t *kp, int strip_str)
685 686 {
686 687 struct ft_list *faultp;
687 688 int i;
688 689 char name[KSTAT_STRLEN + 7]; /* room for 999999 faults */
689 690
690 691 /* PERL_ASSERT(kp->ks_ndata == 1); */
691 692 /* PERL_ASSERT(kp->ks_data_size == sizeof (struct ft_list)); */
692 693
693 694 for (i = 1, faultp = (struct ft_list *)(kp->ks_data);
694 695 i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list);
695 696 i++, faultp++) {
696 697 (void) snprintf(name, sizeof (name), "unit_%d", i);
697 698 hv_store(self, name, strlen(name), newSViv(faultp->unit), 0);
698 699 (void) snprintf(name, sizeof (name), "type_%d", i);
699 700 hv_store(self, name, strlen(name), newSViv(faultp->type), 0);
700 701 (void) snprintf(name, sizeof (name), "fclass_%d", i);
701 702 hv_store(self, name, strlen(name), newSViv(faultp->fclass), 0);
702 703 (void) snprintf(name, sizeof (name), "create_time_%d", i);
703 704 hv_store(self, name, strlen(name),
704 705 NEW_UV(faultp->create_time), 0);
705 706 (void) snprintf(name, sizeof (name), "msg_%d", i);
706 707 hv_store(self, name, strlen(name), newSVpv(faultp->msg, 0), 0);
707 708 }
708 709 }
709 710 #endif
710 711
711 712 /*
712 713 * We need to be able to find the function corresponding to a particular raw
713 714 * kstat. To do this we ignore the instance and glue the module and name
714 715 * together to form a composite key. We can then use the data in the kstat
715 716 * structure to find the appropriate function. We use a perl hash to manage the
716 717 * lookup, where the key is "module:name" and the value is a pointer to the
717 718 * appropriate C function.
718 719 *
719 720 * Note that some kstats include the instance number as part of the module
720 721 * and/or name. This could be construed as a bug. However, to work around this
721 722 * we omit any digits from the module and name as we build the table in
722 723 * build_raw_kstat_loopup(), and we remove any digits from the module and name
723 724 * when we look up the functions in lookup_raw_kstat_fn()
724 725 */
725 726
726 727 /*
727 728 * This function is called when the XS is first dlopen()ed, and builds the
728 729 * lookup table as described above.
729 730 */
730 731
731 732 static void
732 733 build_raw_kstat_lookup()
733 734 {
734 735 /* Create new hash */
735 736 raw_kstat_lookup = newHV();
736 737
737 738 SAVE_FNP(raw_kstat_lookup, save_cpu_stat, "cpu_stat:cpu_stat");
738 739 SAVE_FNP(raw_kstat_lookup, save_var, "unix:var");
739 740 SAVE_FNP(raw_kstat_lookup, save_ncstats, "unix:ncstats");
740 741 SAVE_FNP(raw_kstat_lookup, save_sysinfo, "unix:sysinfo");
741 742 SAVE_FNP(raw_kstat_lookup, save_vminfo, "unix:vminfo");
742 743 SAVE_FNP(raw_kstat_lookup, save_nfs, "nfs:mntinfo");
743 744 #ifdef __sparc
744 745 SAVE_FNP(raw_kstat_lookup, save_sfmmu_global_stat,
745 746 "unix:sfmmu_global_stat");
746 747 SAVE_FNP(raw_kstat_lookup, save_sfmmu_tsbsize_stat,
747 748 "unix:sfmmu_tsbsize_stat");
748 749 SAVE_FNP(raw_kstat_lookup, save_simmstat, "unix:simm-status");
749 750 SAVE_FNP(raw_kstat_lookup, save_temperature, "unix:temperature");
750 751 SAVE_FNP(raw_kstat_lookup, save_temp_over, "unix:temperature override");
751 752 SAVE_FNP(raw_kstat_lookup, save_ps_shadow, "unix:ps_shadow");
752 753 SAVE_FNP(raw_kstat_lookup, save_fault_list, "unix:fault_list");
753 754 #endif
754 755 }
755 756
756 757 /*
757 758 * This finds and returns the raw kstat reader function corresponding to the
758 759 * supplied module and name. If no matching function exists, 0 is returned.
759 760 */
760 761
761 762 static kstat_raw_reader_t lookup_raw_kstat_fn(char *module, char *name)
762 763 {
763 764 char key[KSTAT_STRLEN * 2];
764 765 register char *f, *t;
765 766 SV **entry;
766 767 kstat_raw_reader_t fnp;
767 768
768 769 /* Copy across module & name, removing any digits - see comment above */
769 770 for (f = module, t = key; *f != '\0'; f++, t++) {
770 771 while (*f != '\0' && isdigit(*f)) { f++; }
771 772 *t = *f;
772 773 }
773 774 *t++ = ':';
774 775 for (f = name; *f != '\0'; f++, t++) {
775 776 while (*f != '\0' && isdigit(*f)) {
776 777 f++;
777 778 }
778 779 *t = *f;
779 780 }
780 781 *t = '\0';
781 782
782 783 /* look up & return the function, or teturn 0 if not found */
783 784 if ((entry = hv_fetch(raw_kstat_lookup, key, strlen(key), FALSE)) == 0)
784 785 {
785 786 fnp = 0;
786 787 } else {
787 788 fnp = (kstat_raw_reader_t)(uintptr_t)SvIV(*entry);
788 789 }
789 790 return (fnp);
790 791 }
791 792
792 793 /*
793 794 * This module converts the flat list returned by kstat_read() into a perl hash
794 795 * tree keyed on module, instance, name and statistic. The following functions
795 796 * provide code to create the nested hashes, and to iterate over them.
796 797 */
797 798
798 799 /*
799 800 * Given module, instance and name keys return a pointer to the hash tied to
800 801 * the bottommost hash. If the hash already exists, we just return a pointer
801 802 * to it, otherwise we create the hash and any others also required above it in
802 803 * the hierarchy. The returned tiehash is blessed into the
803 804 * Sun::Solaris::Kstat::_Stat class, so that the appropriate TIEHASH methods are
804 805 * called when the bottommost hash is accessed. If the is_new parameter is
805 806 * non-null it will be set to TRUE if a new tie has been created, and FALSE if
806 807 * the tie already existed.
807 808 */
808 809
809 810 static HV *
810 811 get_tie(SV *self, char *module, int instance, char *name, int *is_new)
811 812 {
812 813 char str_inst[11]; /* big enough for up to 10^10 instances */
813 814 char *key[3]; /* 3 part key: module, instance, name */
814 815 int k;
815 816 int new;
816 817 HV *hash;
817 818 HV *tie;
818 819
819 820 /* Create the keys */
820 821 (void) snprintf(str_inst, sizeof (str_inst), "%d", instance);
821 822 key[0] = module;
822 823 key[1] = str_inst;
823 824 key[2] = name;
824 825
825 826 /* Iteratively descend the tree, creating new hashes as required */
826 827 hash = (HV *)SvRV(self);
827 828 for (k = 0; k < 3; k++) {
828 829 SV **entry;
829 830
830 831 SvREADONLY_off(hash);
831 832 entry = hv_fetch(hash, key[k], strlen(key[k]), TRUE);
832 833
833 834 /* If the entry doesn't exist, create it */
834 835 if (! SvOK(*entry)) {
835 836 HV *newhash;
836 837 SV *rv;
837 838
838 839 newhash = newHV();
839 840 rv = newRV_noinc((SV *)newhash);
840 841 sv_setsv(*entry, rv);
841 842 SvREFCNT_dec(rv);
842 843 if (k < 2) {
843 844 SvREADONLY_on(newhash);
844 845 }
845 846 SvREADONLY_on(*entry);
846 847 SvREADONLY_on(hash);
847 848 hash = newhash;
848 849 new = 1;
849 850
850 851 /* Otherwise it already existed */
851 852 } else {
852 853 SvREADONLY_on(hash);
853 854 hash = (HV *)SvRV(*entry);
854 855 new = 0;
855 856 }
856 857 }
857 858
858 859 /* Create and bless a hash for the tie, if necessary */
859 860 if (new) {
860 861 SV *tieref;
861 862 HV *stash;
862 863
863 864 tie = newHV();
864 865 tieref = newRV_noinc((SV *)tie);
865 866 stash = gv_stashpv("Sun::Solaris::Kstat::_Stat", TRUE);
866 867 sv_bless(tieref, stash);
867 868
868 869 /* Add TIEHASH magic */
869 870 hv_magic(hash, (GV *)tieref, 'P');
870 871 SvREADONLY_on(hash);
871 872
872 873 /* Otherwise, just find the existing tied hash */
873 874 } else {
874 875 MAGIC *mg;
875 876
876 877 mg = mg_find((SV *)hash, 'P');
877 878 PERL_ASSERTMSG(mg != 0, "get_tie: lost P magic");
878 879 tie = (HV *)SvRV(mg->mg_obj);
879 880 }
880 881 if (is_new) {
881 882 *is_new = new;
882 883 }
883 884 return (tie);
884 885 }
885 886
886 887 /*
↓ open down ↓ |
853 lines elided |
↑ open up ↑ |
887 888 * This is an iterator function used to traverse the hash hierarchy and apply
888 889 * the passed function to the tied hashes at the bottom of the hierarchy. If
889 890 * any of the callback functions return 0, 0 is returned, otherwise 1
890 891 */
891 892
892 893 static int
893 894 apply_to_ties(SV *self, ATTCb_t cb, void *arg)
894 895 {
895 896 HV *hash1;
896 897 HE *entry1;
897 - long s;
898 898 int ret;
899 899
900 900 hash1 = (HV *)SvRV(self);
901 901 hv_iterinit(hash1);
902 902 ret = 1;
903 903
904 904 /* Iterate over each module */
905 - while (entry1 = hv_iternext(hash1)) {
905 + while ((entry1 = hv_iternext(hash1))) {
906 906 HV *hash2;
907 907 HE *entry2;
908 908
909 909 hash2 = (HV *)SvRV(hv_iterval(hash1, entry1));
910 910 hv_iterinit(hash2);
911 911
912 912 /* Iterate over each module:instance */
913 - while (entry2 = hv_iternext(hash2)) {
913 + while ((entry2 = hv_iternext(hash2))) {
914 914 HV *hash3;
915 915 HE *entry3;
916 916
917 917 hash3 = (HV *)SvRV(hv_iterval(hash2, entry2));
918 918 hv_iterinit(hash3);
919 919
920 920 /* Iterate over each module:instance:name */
921 - while (entry3 = hv_iternext(hash3)) {
921 + while ((entry3 = hv_iternext(hash3))) {
922 922 HV *hash4;
923 923 MAGIC *mg;
924 - HV *tie;
925 924
926 925 /* Get the tie */
927 926 hash4 = (HV *)SvRV(hv_iterval(hash3, entry3));
928 927 mg = mg_find((SV *)hash4, 'P');
929 928 PERL_ASSERTMSG(mg != 0,
930 929 "apply_to_ties: lost P magic");
931 930
932 931 /* Apply the callback */
933 932 if (! cb((HV *)SvRV(mg->mg_obj), arg)) {
934 933 ret = 0;
935 934 }
936 935 }
937 936 }
938 937 }
939 938 return (ret);
940 939 }
941 940
942 941 /*
943 942 * Mark this HV as valid - used by update() when pruning deleted kstat nodes
944 943 */
945 944
946 945 static int
947 946 set_valid(HV *self, void *arg)
948 947 {
949 948 MAGIC *mg;
950 949
951 950 mg = mg_find((SV *)self, '~');
952 951 PERL_ASSERTMSG(mg != 0, "set_valid: lost ~ magic");
953 952 ((KstatInfo_t *)SvPVX(mg->mg_obj))->valid = (int)(intptr_t)arg;
954 953 return (1);
955 954 }
956 955
957 956 /*
958 957 * Prune invalid kstat nodes. This is called when kstat_chain_update() detects
959 958 * that the kstat chain has been updated. This removes any hash tree entries
960 959 * that no longer have a corresponding kstat. If del is non-null it will be
961 960 * set to the keys of the deleted kstat nodes, if any. If any entries are
962 961 * deleted 1 will be retured, otherwise 0
963 962 */
964 963
965 964 static int
966 965 prune_invalid(SV *self, AV *del)
967 966 {
968 967 HV *hash1;
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
969 968 HE *entry1;
970 969 STRLEN klen;
971 970 char *module, *instance, *name, *key;
972 971 int ret;
973 972
974 973 hash1 = (HV *)SvRV(self);
975 974 hv_iterinit(hash1);
976 975 ret = 0;
977 976
978 977 /* Iterate over each module */
979 - while (entry1 = hv_iternext(hash1)) {
978 + while ((entry1 = hv_iternext(hash1))) {
980 979 HV *hash2;
981 980 HE *entry2;
982 981
983 982 module = HePV(entry1, PL_na);
984 983 hash2 = (HV *)SvRV(hv_iterval(hash1, entry1));
985 984 hv_iterinit(hash2);
986 985
987 986 /* Iterate over each module:instance */
988 - while (entry2 = hv_iternext(hash2)) {
987 + while ((entry2 = hv_iternext(hash2))) {
989 988 HV *hash3;
990 989 HE *entry3;
991 990
992 991 instance = HePV(entry2, PL_na);
993 992 hash3 = (HV *)SvRV(hv_iterval(hash2, entry2));
994 993 hv_iterinit(hash3);
995 994
996 995 /* Iterate over each module:instance:name */
997 - while (entry3 = hv_iternext(hash3)) {
996 + while ((entry3 = hv_iternext(hash3))) {
998 997 HV *hash4;
999 998 MAGIC *mg;
1000 999 HV *tie;
1001 1000
1002 1001 name = HePV(entry3, PL_na);
1003 1002 hash4 = (HV *)SvRV(hv_iterval(hash3, entry3));
1004 1003 mg = mg_find((SV *)hash4, 'P');
1005 1004 PERL_ASSERTMSG(mg != 0,
1006 1005 "prune_invalid: lost P magic");
1007 1006 tie = (HV *)SvRV(mg->mg_obj);
1008 1007 mg = mg_find((SV *)tie, '~');
1009 1008 PERL_ASSERTMSG(mg != 0,
1010 1009 "prune_invalid: lost ~ magic");
1011 1010
1012 1011 /* If this is marked as invalid, prune it */
1013 1012 if (((KstatInfo_t *)SvPVX(
1014 1013 (SV *)mg->mg_obj))->valid == FALSE) {
1015 1014 SvREADONLY_off(hash3);
1016 1015 key = HePV(entry3, klen);
1017 1016 hv_delete(hash3, key, klen, G_DISCARD);
1018 1017 SvREADONLY_on(hash3);
1019 1018 if (del) {
1020 1019 av_push(del,
1021 1020 newSVpvf("%s:%s:%s",
1022 1021 module, instance, name));
1023 1022 }
1024 1023 ret = 1;
1025 1024 }
1026 1025 }
1027 1026
1028 1027 /* If the module:instance:name hash is empty prune it */
1029 1028 if (HvKEYS(hash3) == 0) {
1030 1029 SvREADONLY_off(hash2);
1031 1030 key = HePV(entry2, klen);
1032 1031 hv_delete(hash2, key, klen, G_DISCARD);
1033 1032 SvREADONLY_on(hash2);
1034 1033 }
1035 1034 }
1036 1035 /* If the module:instance hash is empty prune it */
1037 1036 if (HvKEYS(hash2) == 0) {
1038 1037 SvREADONLY_off(hash1);
1039 1038 key = HePV(entry1, klen);
1040 1039 hv_delete(hash1, key, klen, G_DISCARD);
1041 1040 SvREADONLY_on(hash1);
1042 1041 }
1043 1042 }
1044 1043 return (ret);
1045 1044 }
1046 1045
1047 1046 /*
1048 1047 * Named kstats are returned as a list of key/values. This function converts
1049 1048 * such a list into the equivalent perl datatypes, and stores them in the passed
1050 1049 * hash.
1051 1050 */
1052 1051
1053 1052 static void
1054 1053 save_named(HV *self, kstat_t *kp, int strip_str)
1055 1054 {
1056 1055 kstat_named_t *knp;
1057 1056 int n;
1058 1057 SV* value;
1059 1058
1060 1059 for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
1061 1060 switch (knp->data_type) {
1062 1061 case KSTAT_DATA_CHAR:
1063 1062 value = newSVpv(knp->value.c, strip_str ?
1064 1063 strlen(knp->value.c) : sizeof (knp->value.c));
1065 1064 break;
1066 1065 case KSTAT_DATA_INT32:
1067 1066 value = newSViv(knp->value.i32);
1068 1067 break;
1069 1068 case KSTAT_DATA_UINT32:
1070 1069 value = NEW_UV(knp->value.ui32);
1071 1070 break;
1072 1071 case KSTAT_DATA_INT64:
1073 1072 value = NEW_UV(knp->value.i64);
1074 1073 break;
1075 1074 case KSTAT_DATA_UINT64:
1076 1075 value = NEW_UV(knp->value.ui64);
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
1077 1076 break;
1078 1077 case KSTAT_DATA_STRING:
1079 1078 if (KSTAT_NAMED_STR_PTR(knp) == NULL)
1080 1079 value = newSVpv("null", sizeof ("null") - 1);
1081 1080 else
1082 1081 value = newSVpv(KSTAT_NAMED_STR_PTR(knp),
1083 1082 KSTAT_NAMED_STR_BUFLEN(knp) -1);
1084 1083 break;
1085 1084 default:
1086 1085 PERL_ASSERTMSG(0, "kstat_read: invalid data type");
1087 - break;
1086 + continue;
1088 1087 }
1089 1088 hv_store(self, knp->name, strlen(knp->name), value, 0);
1090 1089 }
1091 1090 }
1092 1091
1093 1092 /*
1094 1093 * Save kstat interrupt statistics
1095 1094 */
1096 1095
1097 1096 static void
1098 1097 save_intr(HV *self, kstat_t *kp, int strip_str)
1099 1098 {
1100 1099 kstat_intr_t *kintrp;
1101 1100 int i;
1102 1101 static char *intr_names[] =
1103 1102 { "hard", "soft", "watchdog", "spurious", "multiple_service" };
1104 1103
1105 1104 PERL_ASSERT(kp->ks_ndata == 1);
1106 1105 PERL_ASSERT(kp->ks_data_size == sizeof (kstat_intr_t));
1107 1106 kintrp = KSTAT_INTR_PTR(kp);
1108 1107
1109 1108 for (i = 0; i < KSTAT_NUM_INTRS; i++) {
1110 1109 hv_store(self, intr_names[i], strlen(intr_names[i]),
1111 1110 NEW_UV(kintrp->intrs[i]), 0);
1112 1111 }
1113 1112 }
1114 1113
1115 1114 /*
1116 1115 * Save IO statistics
1117 1116 */
1118 1117
1119 1118 static void
1120 1119 save_io(HV *self, kstat_t *kp, int strip_str)
1121 1120 {
1122 1121 kstat_io_t *kiop;
1123 1122
1124 1123 PERL_ASSERT(kp->ks_ndata == 1);
1125 1124 PERL_ASSERT(kp->ks_data_size == sizeof (kstat_io_t));
1126 1125 kiop = KSTAT_IO_PTR(kp);
1127 1126 SAVE_UINT64(self, kiop, nread);
1128 1127 SAVE_UINT64(self, kiop, nwritten);
1129 1128 SAVE_UINT32(self, kiop, reads);
1130 1129 SAVE_UINT32(self, kiop, writes);
1131 1130 SAVE_HRTIME(self, kiop, wtime);
1132 1131 SAVE_HRTIME(self, kiop, wlentime);
1133 1132 SAVE_HRTIME(self, kiop, wlastupdate);
1134 1133 SAVE_HRTIME(self, kiop, rtime);
1135 1134 SAVE_HRTIME(self, kiop, rlentime);
1136 1135 SAVE_HRTIME(self, kiop, rlastupdate);
1137 1136 SAVE_UINT32(self, kiop, wcnt);
1138 1137 SAVE_UINT32(self, kiop, rcnt);
1139 1138 }
1140 1139
1141 1140 /*
1142 1141 * Save timer statistics
1143 1142 */
1144 1143
1145 1144 static void
1146 1145 save_timer(HV *self, kstat_t *kp, int strip_str)
1147 1146 {
1148 1147 kstat_timer_t *ktimerp;
1149 1148
1150 1149 PERL_ASSERT(kp->ks_ndata == 1);
1151 1150 PERL_ASSERT(kp->ks_data_size == sizeof (kstat_timer_t));
1152 1151 ktimerp = KSTAT_TIMER_PTR(kp);
1153 1152 SAVE_STRING(self, ktimerp, name, strip_str);
1154 1153 SAVE_UINT64(self, ktimerp, num_events);
1155 1154 SAVE_HRTIME(self, ktimerp, elapsed_time);
1156 1155 SAVE_HRTIME(self, ktimerp, min_time);
1157 1156 SAVE_HRTIME(self, ktimerp, max_time);
1158 1157 SAVE_HRTIME(self, ktimerp, start_time);
1159 1158 SAVE_HRTIME(self, ktimerp, stop_time);
1160 1159 }
1161 1160
1162 1161 /*
1163 1162 * Read kstats and copy into the supplied perl hash structure. If refresh is
1164 1163 * true, this function is being called as part of the update() method. In this
1165 1164 * case it is only necessary to read the kstats if they have previously been
1166 1165 * accessed (kip->read == TRUE). If refresh is false, this function is being
1167 1166 * called prior to returning a value to the caller. In this case, it is only
1168 1167 * necessary to read the kstats if they have not previously been read. If the
1169 1168 * kstat_read() fails, 0 is returned, otherwise 1
1170 1169 */
1171 1170
1172 1171 static int
1173 1172 read_kstats(HV *self, int refresh)
1174 1173 {
1175 1174 MAGIC *mg;
1176 1175 KstatInfo_t *kip;
1177 1176 kstat_raw_reader_t fnp;
1178 1177
1179 1178 /* Find the MAGIC KstatInfo_t data structure */
1180 1179 mg = mg_find((SV *)self, '~');
1181 1180 PERL_ASSERTMSG(mg != 0, "read_kstats: lost ~ magic");
1182 1181 kip = (KstatInfo_t *)SvPVX(mg->mg_obj);
1183 1182
1184 1183 /* Return early if we don't need to actually read the kstats */
1185 1184 if ((refresh && ! kip->read) || (! refresh && kip->read)) {
1186 1185 return (1);
1187 1186 }
1188 1187
1189 1188 /* Read the kstats and return 0 if this fails */
1190 1189 if (kstat_read(kip->kstat_ctl, kip->kstat, NULL) < 0) {
1191 1190 return (0);
1192 1191 }
1193 1192
1194 1193 /* Save the read data */
1195 1194 hv_store(self, "snaptime", 8, NEW_HRTIME(kip->kstat->ks_snaptime), 0);
1196 1195 switch (kip->kstat->ks_type) {
1197 1196 case KSTAT_TYPE_RAW:
1198 1197 if ((fnp = lookup_raw_kstat_fn(kip->kstat->ks_module,
1199 1198 kip->kstat->ks_name)) != 0) {
1200 1199 fnp(self, kip->kstat, kip->strip_str);
1201 1200 }
1202 1201 break;
1203 1202 case KSTAT_TYPE_NAMED:
1204 1203 save_named(self, kip->kstat, kip->strip_str);
1205 1204 break;
1206 1205 case KSTAT_TYPE_INTR:
1207 1206 save_intr(self, kip->kstat, kip->strip_str);
1208 1207 break;
1209 1208 case KSTAT_TYPE_IO:
1210 1209 save_io(self, kip->kstat, kip->strip_str);
1211 1210 break;
1212 1211 case KSTAT_TYPE_TIMER:
1213 1212 save_timer(self, kip->kstat, kip->strip_str);
1214 1213 break;
1215 1214 default:
1216 1215 PERL_ASSERTMSG(0, "read_kstats: illegal kstat type");
1217 1216 break;
1218 1217 }
1219 1218 kip->read = TRUE;
1220 1219 return (1);
1221 1220 }
1222 1221
1223 1222 /*
1224 1223 * The XS code exported to perl is below here. Note that the XS preprocessor
1225 1224 * has its own commenting syntax, so all comments from this point on are in
1226 1225 * that form.
1227 1226 */
1228 1227
1229 1228 /* The following XS methods are the ABI of the Sun::Solaris::Kstat package */
1230 1229
1231 1230 MODULE = Sun::Solaris::Kstat PACKAGE = Sun::Solaris::Kstat
1232 1231 PROTOTYPES: ENABLE
1233 1232
1234 1233 # Create the raw kstat to store function lookup table on load
1235 1234 BOOT:
1236 1235 build_raw_kstat_lookup();
1237 1236
1238 1237 #
1239 1238 # The Sun::Solaris::Kstat constructor. This builds the nested
1240 1239 # name::instance::module hash structure, but doesn't actually read the
1241 1240 # underlying kstats. This is done on demand by the TIEHASH methods in
1242 1241 # Sun::Solaris::Kstat::_Stat
1243 1242 #
1244 1243
1245 1244 SV*
1246 1245 new(class, ...)
1247 1246 char *class;
1248 1247 PREINIT:
1249 1248 HV *stash;
1250 1249 kstat_ctl_t *kc;
1251 1250 SV *kcsv;
1252 1251 kstat_t *kp;
1253 1252 KstatInfo_t kstatinfo;
1254 1253 int sp, strip_str;
1255 1254 CODE:
1256 1255 /* Check we have an even number of arguments, excluding the class */
1257 1256 sp = 1;
1258 1257 if (((items - sp) % 2) != 0) {
1259 1258 croak(DEBUG_ID ": new: invalid number of arguments");
1260 1259 }
1261 1260
1262 1261 /* Process any (name => value) arguments */
1263 1262 strip_str = 0;
1264 1263 while (sp < items) {
1265 1264 SV *name, *value;
1266 1265
1267 1266 name = ST(sp);
1268 1267 sp++;
1269 1268 value = ST(sp);
1270 1269 sp++;
1271 1270 if (strcmp(SvPVX(name), "strip_strings") == 0) {
1272 1271 strip_str = SvTRUE(value);
1273 1272 } else {
1274 1273 croak(DEBUG_ID ": new: invalid parameter name '%s'",
1275 1274 SvPVX(name));
1276 1275 }
1277 1276 }
1278 1277
1279 1278 /* Open the kstats handle */
1280 1279 if ((kc = kstat_open()) == 0) {
1281 1280 XSRETURN_UNDEF;
1282 1281 }
1283 1282
1284 1283 /* Create a blessed hash ref */
1285 1284 RETVAL = (SV *)newRV_noinc((SV *)newHV());
1286 1285 stash = gv_stashpv(class, TRUE);
1287 1286 sv_bless(RETVAL, stash);
1288 1287
1289 1288 /* Create a place to save the KstatInfo_t structure */
1290 1289 kcsv = newSVpv((char *)&kc, sizeof (kc));
1291 1290 sv_magic(SvRV(RETVAL), kcsv, '~', 0, 0);
1292 1291 SvREFCNT_dec(kcsv);
1293 1292
1294 1293 /* Initialise the KstatsInfo_t structure */
1295 1294 kstatinfo.read = FALSE;
1296 1295 kstatinfo.valid = TRUE;
1297 1296 kstatinfo.strip_str = strip_str;
1298 1297 kstatinfo.kstat_ctl = kc;
1299 1298
1300 1299 /* Scan the kstat chain, building hash entries for the kstats */
1301 1300 for (kp = kc->kc_chain; kp != 0; kp = kp->ks_next) {
1302 1301 HV *tie;
1303 1302 SV *kstatsv;
1304 1303
1305 1304 /* Don't bother storing the kstat headers */
1306 1305 if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
1307 1306 continue;
1308 1307 }
1309 1308
1310 1309 /* Don't bother storing raw stats we don't understand */
1311 1310 if (kp->ks_type == KSTAT_TYPE_RAW &&
1312 1311 lookup_raw_kstat_fn(kp->ks_module, kp->ks_name) == 0) {
1313 1312 #ifdef REPORT_UNKNOWN
1314 1313 (void) fprintf(stderr,
1315 1314 "Unknown kstat type %s:%d:%s - %d of size %d\n",
1316 1315 kp->ks_module, kp->ks_instance, kp->ks_name,
1317 1316 kp->ks_ndata, kp->ks_data_size);
1318 1317 #endif
1319 1318 continue;
1320 1319 }
1321 1320
1322 1321 /* Create a 3-layer hash hierarchy - module.instance.name */
1323 1322 tie = get_tie(RETVAL, kp->ks_module, kp->ks_instance,
1324 1323 kp->ks_name, 0);
1325 1324
1326 1325 /* Save the data necessary to read the kstat info on demand */
1327 1326 hv_store(tie, "class", 5, newSVpv(kp->ks_class, 0), 0);
1328 1327 hv_store(tie, "crtime", 6, NEW_HRTIME(kp->ks_crtime), 0);
1329 1328 kstatinfo.kstat = kp;
1330 1329 kstatsv = newSVpv((char *)&kstatinfo, sizeof (kstatinfo));
1331 1330 sv_magic((SV *)tie, kstatsv, '~', 0, 0);
1332 1331 SvREFCNT_dec(kstatsv);
1333 1332 }
1334 1333 SvREADONLY_on(SvRV(RETVAL));
1335 1334 /* SvREADONLY_on(RETVAL); */
1336 1335 OUTPUT:
1337 1336 RETVAL
1338 1337
1339 1338 #
1340 1339 # Update the perl hash structure so that it is in line with the kernel kstats
1341 1340 # data. Only kstats athat have previously been accessed are read,
1342 1341 #
1343 1342
1344 1343 # Scalar context: true/false
1345 1344 # Array context: (\@added, \@deleted)
1346 1345 void
1347 1346 update(self)
1348 1347 SV* self;
1349 1348 PREINIT:
1350 1349 MAGIC *mg;
1351 1350 kstat_ctl_t *kc;
1352 1351 kstat_t *kp;
1353 1352 int ret;
1354 1353 AV *add, *del;
1355 1354 PPCODE:
1356 1355 /* Find the hidden KstatInfo_t structure */
1357 1356 mg = mg_find(SvRV(self), '~');
1358 1357 PERL_ASSERTMSG(mg != 0, "update: lost ~ magic");
1359 1358 kc = *(kstat_ctl_t **)SvPVX(mg->mg_obj);
1360 1359
1361 1360 /* Update the kstat chain, and return immediately on error. */
1362 1361 if ((ret = kstat_chain_update(kc)) == -1) {
1363 1362 if (GIMME_V == G_ARRAY) {
1364 1363 EXTEND(SP, 2);
1365 1364 PUSHs(sv_newmortal());
1366 1365 PUSHs(sv_newmortal());
1367 1366 } else {
1368 1367 EXTEND(SP, 1);
1369 1368 PUSHs(sv_2mortal(newSViv(ret)));
1370 1369 }
1371 1370 }
1372 1371
1373 1372 /* Create the arrays to be returned if in an array context */
1374 1373 if (GIMME_V == G_ARRAY) {
1375 1374 add = newAV();
1376 1375 del = newAV();
1377 1376 } else {
1378 1377 add = 0;
1379 1378 del = 0;
1380 1379 }
1381 1380
1382 1381 /*
1383 1382 * If the kstat chain hasn't changed we can just reread any stats
1384 1383 * that have already been read
1385 1384 */
1386 1385 if (ret == 0) {
1387 1386 if (! apply_to_ties(self, (ATTCb_t)read_kstats, (void *)TRUE)) {
1388 1387 if (GIMME_V == G_ARRAY) {
1389 1388 EXTEND(SP, 2);
1390 1389 PUSHs(sv_2mortal(newRV_noinc((SV *)add)));
1391 1390 PUSHs(sv_2mortal(newRV_noinc((SV *)del)));
1392 1391 } else {
1393 1392 EXTEND(SP, 1);
1394 1393 PUSHs(sv_2mortal(newSViv(-1)));
1395 1394 }
1396 1395 }
1397 1396
1398 1397 /*
1399 1398 * Otherwise we have to update the Perl structure so that it is in
1400 1399 * agreement with the new kstat chain. We do this in such a way as to
1401 1400 * retain all the existing structures, just adding or deleting the
1402 1401 * bare minimum.
1403 1402 */
1404 1403 } else {
1405 1404 KstatInfo_t kstatinfo;
1406 1405
1407 1406 /*
1408 1407 * Step 1: set the 'invalid' flag on each entry
1409 1408 */
1410 1409 apply_to_ties(self, &set_valid, (void *)FALSE);
1411 1410
1412 1411 /*
1413 1412 * Step 2: Set the 'valid' flag on all entries still in the
1414 1413 * kernel kstat chain
1415 1414 */
1416 1415 kstatinfo.read = FALSE;
1417 1416 kstatinfo.valid = TRUE;
1418 1417 kstatinfo.kstat_ctl = kc;
1419 1418 for (kp = kc->kc_chain; kp != 0; kp = kp->ks_next) {
1420 1419 int new;
1421 1420 HV *tie;
1422 1421
1423 1422 /* Don't bother storing the kstat headers or types */
1424 1423 if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
1425 1424 continue;
1426 1425 }
1427 1426
1428 1427 /* Don't bother storing raw stats we don't understand */
1429 1428 if (kp->ks_type == KSTAT_TYPE_RAW &&
1430 1429 lookup_raw_kstat_fn(kp->ks_module, kp->ks_name)
1431 1430 == 0) {
1432 1431 #ifdef REPORT_UNKNOWN
1433 1432 (void) printf("Unknown kstat type %s:%d:%s "
1434 1433 "- %d of size %d\n", kp->ks_module,
1435 1434 kp->ks_instance, kp->ks_name,
1436 1435 kp->ks_ndata, kp->ks_data_size);
1437 1436 #endif
1438 1437 continue;
1439 1438 }
1440 1439
1441 1440 /* Find the tied hash associated with the kstat entry */
1442 1441 tie = get_tie(self, kp->ks_module, kp->ks_instance,
1443 1442 kp->ks_name, &new);
1444 1443
1445 1444 /* If newly created store the associated kstat info */
1446 1445 if (new) {
1447 1446 SV *kstatsv;
1448 1447
1449 1448 /*
1450 1449 * Save the data necessary to read the kstat
1451 1450 * info on demand
1452 1451 */
1453 1452 hv_store(tie, "class", 5,
1454 1453 newSVpv(kp->ks_class, 0), 0);
1455 1454 hv_store(tie, "crtime", 6,
1456 1455 NEW_HRTIME(kp->ks_crtime), 0);
1457 1456 kstatinfo.kstat = kp;
1458 1457 kstatsv = newSVpv((char *)&kstatinfo,
1459 1458 sizeof (kstatinfo));
1460 1459 sv_magic((SV *)tie, kstatsv, '~', 0, 0);
1461 1460 SvREFCNT_dec(kstatsv);
1462 1461
1463 1462 /* Save the key on the add list, if required */
1464 1463 if (GIMME_V == G_ARRAY) {
1465 1464 av_push(add, newSVpvf("%s:%d:%s",
1466 1465 kp->ks_module, kp->ks_instance,
1467 1466 kp->ks_name));
1468 1467 }
1469 1468
1470 1469 /* If the stats already exist, just update them */
1471 1470 } else {
1472 1471 MAGIC *mg;
1473 1472 KstatInfo_t *kip;
1474 1473
1475 1474 /* Find the hidden KstatInfo_t */
1476 1475 mg = mg_find((SV *)tie, '~');
1477 1476 PERL_ASSERTMSG(mg != 0, "update: lost ~ magic");
1478 1477 kip = (KstatInfo_t *)SvPVX(mg->mg_obj);
1479 1478
1480 1479 /* Mark the tie as valid */
1481 1480 kip->valid = TRUE;
1482 1481
1483 1482 /* Re-save the kstat_t pointer. If the kstat
1484 1483 * has been deleted and re-added since the last
1485 1484 * update, the address of the kstat structure
1486 1485 * will have changed, even though the kstat will
1487 1486 * still live at the same place in the perl
1488 1487 * hash tree structure.
1489 1488 */
1490 1489 kip->kstat = kp;
1491 1490
1492 1491 /* Reread the stats, if read previously */
1493 1492 read_kstats(tie, TRUE);
1494 1493 }
1495 1494 }
1496 1495
1497 1496 /*
1498 1497 *Step 3: Delete any entries still marked as 'invalid'
1499 1498 */
1500 1499 ret = prune_invalid(self, del);
1501 1500
1502 1501 }
1503 1502 if (GIMME_V == G_ARRAY) {
1504 1503 EXTEND(SP, 2);
1505 1504 PUSHs(sv_2mortal(newRV_noinc((SV *)add)));
1506 1505 PUSHs(sv_2mortal(newRV_noinc((SV *)del)));
1507 1506 } else {
1508 1507 EXTEND(SP, 1);
1509 1508 PUSHs(sv_2mortal(newSViv(ret)));
1510 1509 }
1511 1510
1512 1511
1513 1512 #
1514 1513 # Destructor. Closes the kstat connection
1515 1514 #
1516 1515
1517 1516 void
1518 1517 DESTROY(self)
1519 1518 SV *self;
1520 1519 PREINIT:
1521 1520 MAGIC *mg;
1522 1521 kstat_ctl_t *kc;
1523 1522 CODE:
1524 1523 mg = mg_find(SvRV(self), '~');
1525 1524 PERL_ASSERTMSG(mg != 0, "DESTROY: lost ~ magic");
1526 1525 kc = *(kstat_ctl_t **)SvPVX(mg->mg_obj);
1527 1526 if (kstat_close(kc) != 0) {
1528 1527 croak(DEBUG_ID ": kstat_close: failed");
1529 1528 }
1530 1529
1531 1530 #
1532 1531 # The following XS methods implement the TIEHASH mechanism used to update the
1533 1532 # kstats hash structure. These are blessed into a package that isn't
1534 1533 # visible to callers of the Sun::Solaris::Kstat module
1535 1534 #
1536 1535
1537 1536 MODULE = Sun::Solaris::Kstat PACKAGE = Sun::Solaris::Kstat::_Stat
1538 1537 PROTOTYPES: ENABLE
1539 1538
1540 1539 #
1541 1540 # If a value has already been read, return it. Otherwise read the appropriate
1542 1541 # kstat and then return the value
1543 1542 #
1544 1543
1545 1544 SV*
1546 1545 FETCH(self, key)
1547 1546 SV* self;
1548 1547 SV* key;
1549 1548 PREINIT:
1550 1549 char *k;
1551 1550 STRLEN klen;
1552 1551 SV **value;
1553 1552 CODE:
1554 1553 self = SvRV(self);
1555 1554 k = SvPV(key, klen);
1556 1555 if (strNE(k, "class") && strNE(k, "crtime")) {
1557 1556 read_kstats((HV *)self, FALSE);
1558 1557 }
1559 1558 value = hv_fetch((HV *)self, k, klen, FALSE);
1560 1559 if (value) {
1561 1560 RETVAL = *value; SvREFCNT_inc(RETVAL);
1562 1561 } else {
1563 1562 RETVAL = &PL_sv_undef;
1564 1563 }
1565 1564 OUTPUT:
1566 1565 RETVAL
1567 1566
1568 1567 #
1569 1568 # Save the passed value into the kstat hash. Read the appropriate kstat first,
1570 1569 # if necessary. Note that this DOES NOT update the underlying kernel kstat
1571 1570 # structure.
1572 1571 #
1573 1572
1574 1573 SV*
1575 1574 STORE(self, key, value)
1576 1575 SV* self;
1577 1576 SV* key;
1578 1577 SV* value;
1579 1578 PREINIT:
1580 1579 char *k;
1581 1580 STRLEN klen;
1582 1581 CODE:
1583 1582 self = SvRV(self);
1584 1583 k = SvPV(key, klen);
1585 1584 if (strNE(k, "class") && strNE(k, "crtime")) {
1586 1585 read_kstats((HV *)self, FALSE);
1587 1586 }
1588 1587 SvREFCNT_inc(value);
1589 1588 RETVAL = *(hv_store((HV *)self, k, klen, value, 0));
1590 1589 SvREFCNT_inc(RETVAL);
1591 1590 OUTPUT:
1592 1591 RETVAL
1593 1592
1594 1593 #
1595 1594 # Check for the existence of the passed key. Read the kstat first if necessary
1596 1595 #
1597 1596
1598 1597 bool
1599 1598 EXISTS(self, key)
1600 1599 SV* self;
1601 1600 SV* key;
1602 1601 PREINIT:
1603 1602 char *k;
1604 1603 CODE:
1605 1604 self = SvRV(self);
1606 1605 k = SvPV(key, PL_na);
1607 1606 if (strNE(k, "class") && strNE(k, "crtime")) {
1608 1607 read_kstats((HV *)self, FALSE);
1609 1608 }
1610 1609 RETVAL = hv_exists_ent((HV *)self, key, 0);
1611 1610 OUTPUT:
1612 1611 RETVAL
1613 1612
1614 1613
1615 1614 #
1616 1615 # Hash iterator initialisation. Read the kstats if necessary.
1617 1616 #
↓ open down ↓ |
520 lines elided |
↑ open up ↑ |
1618 1617
1619 1618 SV*
1620 1619 FIRSTKEY(self)
1621 1620 SV* self;
1622 1621 PREINIT:
1623 1622 HE *he;
1624 1623 PPCODE:
1625 1624 self = SvRV(self);
1626 1625 read_kstats((HV *)self, FALSE);
1627 1626 hv_iterinit((HV *)self);
1628 - if (he = hv_iternext((HV *)self)) {
1627 + if ((he = hv_iternext((HV *)self))) {
1629 1628 EXTEND(SP, 1);
1630 1629 PUSHs(hv_iterkeysv(he));
1631 1630 }
1632 1631
1633 1632 #
1634 1633 # Return hash iterator next value. Read the kstats if necessary.
1635 1634 #
1636 1635
1637 1636 SV*
1638 1637 NEXTKEY(self, lastkey)
1639 1638 SV* self;
1640 1639 SV* lastkey;
1641 1640 PREINIT:
1642 1641 HE *he;
1643 1642 PPCODE:
1644 1643 self = SvRV(self);
1645 - if (he = hv_iternext((HV *)self)) {
1644 + if ((he = hv_iternext((HV *)self))) {
1646 1645 EXTEND(SP, 1);
1647 1646 PUSHs(hv_iterkeysv(he));
1648 1647 }
1649 1648
1650 1649
1651 1650 #
1652 1651 # Delete the specified hash entry.
1653 1652 #
1654 1653
1655 1654 SV*
1656 1655 DELETE(self, key)
1657 1656 SV *self;
1658 1657 SV *key;
1659 1658 CODE:
1660 1659 self = SvRV(self);
1661 1660 RETVAL = hv_delete_ent((HV *)self, key, 0, 0);
1662 1661 if (RETVAL) {
1663 1662 SvREFCNT_inc(RETVAL);
1664 1663 } else {
1665 1664 RETVAL = &PL_sv_undef;
1666 1665 }
1667 1666 OUTPUT:
1668 1667 RETVAL
1669 1668
1670 1669 #
1671 1670 # Clear the entire hash. This will stop any update() calls rereading this
1672 1671 # kstat until it is accessed again.
1673 1672 #
1674 1673
1675 1674 void
1676 1675 CLEAR(self)
1677 1676 SV* self;
1678 1677 PREINIT:
1679 1678 MAGIC *mg;
1680 1679 KstatInfo_t *kip;
1681 1680 CODE:
1682 1681 self = SvRV(self);
1683 1682 hv_clear((HV *)self);
1684 1683 mg = mg_find(self, '~');
1685 1684 PERL_ASSERTMSG(mg != 0, "CLEAR: lost ~ magic");
1686 1685 kip = (KstatInfo_t *)SvPVX(mg->mg_obj);
1687 1686 kip->read = FALSE;
1688 1687 kip->valid = TRUE;
1689 1688 hv_store((HV *)self, "class", 5, newSVpv(kip->kstat->ks_class, 0), 0);
1690 1689 hv_store((HV *)self, "crtime", 6, NEW_HRTIME(kip->kstat->ks_crtime), 0);
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX