4246 kstat read improperly returned ENOMEM
[illumos-gate.git] / usr / src / uts / common / os / kstat_fr.c
blobfb5333921d27c709c0bb7bd6eec46cd46fd78426
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2013, Joyent, Inc. All rights reserved.
27 * Kernel statistics framework
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #include <sys/systm.h>
33 #include <sys/vmsystm.h>
34 #include <sys/t_lock.h>
35 #include <sys/param.h>
36 #include <sys/errno.h>
37 #include <sys/vmem.h>
38 #include <sys/sysmacros.h>
39 #include <sys/cmn_err.h>
40 #include <sys/kstat.h>
41 #include <sys/sysinfo.h>
42 #include <sys/cpuvar.h>
43 #include <sys/fcntl.h>
44 #include <sys/flock.h>
45 #include <sys/vnode.h>
46 #include <sys/vfs.h>
47 #include <sys/dnlc.h>
48 #include <sys/var.h>
49 #include <sys/debug.h>
50 #include <sys/kobj.h>
51 #include <sys/avl.h>
52 #include <sys/pool_pset.h>
53 #include <sys/cpupart.h>
54 #include <sys/zone.h>
55 #include <sys/loadavg.h>
56 #include <vm/page.h>
57 #include <vm/anon.h>
58 #include <vm/seg_kmem.h>
61 * Global lock to protect the AVL trees and kstat_chain_id.
63 static kmutex_t kstat_chain_lock;
66 * Every install/delete kstat bumps kstat_chain_id. This is used by:
68 * (1) /dev/kstat, to detect changes in the kstat chain across ioctls;
70 * (2) kstat_create(), to assign a KID (kstat ID) to each new kstat.
71 * /dev/kstat uses the KID as a cookie for kstat lookups.
73 * We reserve the first two IDs because some kstats are created before
74 * the well-known ones (kstat_headers = 0, kstat_types = 1).
76 * We also bump the kstat_chain_id if a zone is gaining or losing visibility
77 * into a particular kstat, which is logically equivalent to a kstat being
78 * installed/deleted.
81 kid_t kstat_chain_id = 2;
84 * As far as zones are concerned, there are 3 types of kstat:
86 * 1) Those which have a well-known name, and which should return per-zone data
87 * depending on which zone is doing the kstat_read(). sockfs:0:sock_unix_list
88 * is an example of this type of kstat.
90 * 2) Those which should only be exported to a particular list of zones.
91 * For example, in the case of nfs:*:mntinfo, we don't want zone A to be
92 * able to see NFS mounts associated with zone B, while we want the
93 * global zone to be able to see all mounts on the system.
95 * 3) Those that can be exported to all zones. Most system-related
96 * kstats fall within this category.
98 * An ekstat_t thus contains a list of kstats that the zone is to be
99 * exported to. The lookup of a name:instance:module thus translates to a
100 * lookup of name:instance:module:myzone; if the kstat is not exported
101 * to all zones, and does not have the caller's zoneid explicitly
102 * enumerated in the list of zones to be exported to, it is the same as
103 * if the kstat didn't exist.
105 * Writing to kstats is currently disallowed from within a non-global
106 * zone, although this restriction could be removed in the future.
108 typedef struct kstat_zone {
109 zoneid_t zoneid;
110 struct kstat_zone *next;
111 } kstat_zone_t;
114 * Extended kstat structure -- for internal use only.
116 typedef struct ekstat {
117 kstat_t e_ks; /* the kstat itself */
118 size_t e_size; /* total allocation size */
119 kthread_t *e_owner; /* thread holding this kstat */
120 kcondvar_t e_cv; /* wait for owner == NULL */
121 avl_node_t e_avl_bykid; /* AVL tree to sort by KID */
122 avl_node_t e_avl_byname; /* AVL tree to sort by name */
123 kstat_zone_t e_zone; /* zone to export stats to */
124 } ekstat_t;
126 static uint64_t kstat_initial[8192];
127 static void *kstat_initial_ptr = kstat_initial;
128 static size_t kstat_initial_avail = sizeof (kstat_initial);
129 static vmem_t *kstat_arena;
131 #define KSTAT_ALIGN (sizeof (uint64_t))
133 static avl_tree_t kstat_avl_bykid;
134 static avl_tree_t kstat_avl_byname;
137 * Various pointers we need to create kstats at boot time in kstat_init()
139 extern kstat_named_t *segmapcnt_ptr;
140 extern uint_t segmapcnt_ndata;
141 extern int segmap_kstat_update(kstat_t *, int);
142 extern kstat_named_t *biostats_ptr;
143 extern uint_t biostats_ndata;
144 extern kstat_named_t *pollstats_ptr;
145 extern uint_t pollstats_ndata;
147 extern int vac;
148 extern uint_t nproc;
149 extern time_t boot_time;
150 extern sysinfo_t sysinfo;
151 extern vminfo_t vminfo;
153 struct {
154 kstat_named_t ncpus;
155 kstat_named_t lbolt;
156 kstat_named_t deficit;
157 kstat_named_t clk_intr;
158 kstat_named_t vac;
159 kstat_named_t nproc;
160 kstat_named_t avenrun_1min;
161 kstat_named_t avenrun_5min;
162 kstat_named_t avenrun_15min;
163 kstat_named_t boot_time;
164 } system_misc_kstat = {
165 { "ncpus", KSTAT_DATA_UINT32 },
166 { "lbolt", KSTAT_DATA_UINT32 },
167 { "deficit", KSTAT_DATA_UINT32 },
168 { "clk_intr", KSTAT_DATA_UINT32 },
169 { "vac", KSTAT_DATA_UINT32 },
170 { "nproc", KSTAT_DATA_UINT32 },
171 { "avenrun_1min", KSTAT_DATA_UINT32 },
172 { "avenrun_5min", KSTAT_DATA_UINT32 },
173 { "avenrun_15min", KSTAT_DATA_UINT32 },
174 { "boot_time", KSTAT_DATA_UINT32 },
177 struct {
178 kstat_named_t physmem;
179 kstat_named_t nalloc;
180 kstat_named_t nfree;
181 kstat_named_t nalloc_calls;
182 kstat_named_t nfree_calls;
183 kstat_named_t kernelbase;
184 kstat_named_t econtig;
185 kstat_named_t freemem;
186 kstat_named_t availrmem;
187 kstat_named_t lotsfree;
188 kstat_named_t desfree;
189 kstat_named_t minfree;
190 kstat_named_t fastscan;
191 kstat_named_t slowscan;
192 kstat_named_t nscan;
193 kstat_named_t desscan;
194 kstat_named_t pp_kernel;
195 kstat_named_t pagesfree;
196 kstat_named_t pageslocked;
197 kstat_named_t pagestotal;
198 } system_pages_kstat = {
199 { "physmem", KSTAT_DATA_ULONG },
200 { "nalloc", KSTAT_DATA_ULONG },
201 { "nfree", KSTAT_DATA_ULONG },
202 { "nalloc_calls", KSTAT_DATA_ULONG },
203 { "nfree_calls", KSTAT_DATA_ULONG },
204 { "kernelbase", KSTAT_DATA_ULONG },
205 { "econtig", KSTAT_DATA_ULONG },
206 { "freemem", KSTAT_DATA_ULONG },
207 { "availrmem", KSTAT_DATA_ULONG },
208 { "lotsfree", KSTAT_DATA_ULONG },
209 { "desfree", KSTAT_DATA_ULONG },
210 { "minfree", KSTAT_DATA_ULONG },
211 { "fastscan", KSTAT_DATA_ULONG },
212 { "slowscan", KSTAT_DATA_ULONG },
213 { "nscan", KSTAT_DATA_ULONG },
214 { "desscan", KSTAT_DATA_ULONG },
215 { "pp_kernel", KSTAT_DATA_ULONG },
216 { "pagesfree", KSTAT_DATA_ULONG },
217 { "pageslocked", KSTAT_DATA_ULONG },
218 { "pagestotal", KSTAT_DATA_ULONG },
221 static int header_kstat_update(kstat_t *, int);
222 static int header_kstat_snapshot(kstat_t *, void *, int);
223 static int system_misc_kstat_update(kstat_t *, int);
224 static int system_pages_kstat_update(kstat_t *, int);
226 static struct {
227 char name[KSTAT_STRLEN];
228 size_t size;
229 uint_t min_ndata;
230 uint_t max_ndata;
231 } kstat_data_type[KSTAT_NUM_TYPES] = {
232 { "raw", 1, 0, INT_MAX },
233 { "name=value", sizeof (kstat_named_t), 0, INT_MAX },
234 { "interrupt", sizeof (kstat_intr_t), 1, 1 },
235 { "i/o", sizeof (kstat_io_t), 1, 1 },
236 { "event_timer", sizeof (kstat_timer_t), 0, INT_MAX },
240 kstat_zone_find(kstat_t *k, zoneid_t zoneid)
242 ekstat_t *e = (ekstat_t *)k;
243 kstat_zone_t *kz;
245 ASSERT(MUTEX_HELD(&kstat_chain_lock));
246 for (kz = &e->e_zone; kz != NULL; kz = kz->next) {
247 if (zoneid == ALL_ZONES || kz->zoneid == ALL_ZONES)
248 return (1);
249 if (zoneid == kz->zoneid)
250 return (1);
252 return (0);
255 void
256 kstat_zone_remove(kstat_t *k, zoneid_t zoneid)
258 ekstat_t *e = (ekstat_t *)k;
259 kstat_zone_t *kz, *t = NULL;
261 mutex_enter(&kstat_chain_lock);
262 if (zoneid == e->e_zone.zoneid) {
263 kz = e->e_zone.next;
264 ASSERT(kz != NULL);
265 e->e_zone.zoneid = kz->zoneid;
266 e->e_zone.next = kz->next;
267 goto out;
269 for (kz = &e->e_zone; kz->next != NULL; kz = kz->next) {
270 if (kz->next->zoneid == zoneid) {
271 t = kz->next;
272 kz->next = t->next;
273 break;
276 ASSERT(t != NULL); /* we removed something */
277 kz = t;
278 out:
279 kstat_chain_id++;
280 mutex_exit(&kstat_chain_lock);
281 kmem_free(kz, sizeof (*kz));
284 void
285 kstat_zone_add(kstat_t *k, zoneid_t zoneid)
287 ekstat_t *e = (ekstat_t *)k;
288 kstat_zone_t *kz;
290 kz = kmem_alloc(sizeof (*kz), KM_NOSLEEP);
291 if (kz == NULL)
292 return;
293 mutex_enter(&kstat_chain_lock);
294 kz->zoneid = zoneid;
295 kz->next = e->e_zone.next;
296 e->e_zone.next = kz;
297 kstat_chain_id++;
298 mutex_exit(&kstat_chain_lock);
302 * Compare the list of zones for the given kstats, returning 0 if they match
303 * (ie, one list contains ALL_ZONES or both lists contain the same zoneid).
304 * In practice, this is called indirectly by kstat_hold_byname(), so one of the
305 * two lists always has one element, and this is an O(n) operation rather than
306 * O(n^2).
308 static int
309 kstat_zone_compare(ekstat_t *e1, ekstat_t *e2)
311 kstat_zone_t *kz1, *kz2;
313 ASSERT(MUTEX_HELD(&kstat_chain_lock));
314 for (kz1 = &e1->e_zone; kz1 != NULL; kz1 = kz1->next) {
315 for (kz2 = &e2->e_zone; kz2 != NULL; kz2 = kz2->next) {
316 if (kz1->zoneid == ALL_ZONES ||
317 kz2->zoneid == ALL_ZONES)
318 return (0);
319 if (kz1->zoneid == kz2->zoneid)
320 return (0);
323 return (e1->e_zone.zoneid < e2->e_zone.zoneid ? -1 : 1);
327 * Support for keeping kstats sorted in AVL trees for fast lookups.
329 static int
330 kstat_compare_bykid(const void *a1, const void *a2)
332 const kstat_t *k1 = a1;
333 const kstat_t *k2 = a2;
335 if (k1->ks_kid < k2->ks_kid)
336 return (-1);
337 if (k1->ks_kid > k2->ks_kid)
338 return (1);
339 return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
342 static int
343 kstat_compare_byname(const void *a1, const void *a2)
345 const kstat_t *k1 = a1;
346 const kstat_t *k2 = a2;
347 int s;
349 s = strcmp(k1->ks_module, k2->ks_module);
350 if (s > 0)
351 return (1);
352 if (s < 0)
353 return (-1);
355 if (k1->ks_instance < k2->ks_instance)
356 return (-1);
357 if (k1->ks_instance > k2->ks_instance)
358 return (1);
360 s = strcmp(k1->ks_name, k2->ks_name);
361 if (s > 0)
362 return (1);
363 if (s < 0)
364 return (-1);
366 return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
369 static kstat_t *
370 kstat_hold(avl_tree_t *t, ekstat_t *template)
372 kstat_t *ksp;
373 ekstat_t *e;
375 mutex_enter(&kstat_chain_lock);
376 for (;;) {
377 ksp = avl_find(t, template, NULL);
378 if (ksp == NULL)
379 break;
380 e = (ekstat_t *)ksp;
381 if (e->e_owner == NULL) {
382 e->e_owner = curthread;
383 break;
385 cv_wait(&e->e_cv, &kstat_chain_lock);
387 mutex_exit(&kstat_chain_lock);
388 return (ksp);
391 void
392 kstat_rele(kstat_t *ksp)
394 ekstat_t *e = (ekstat_t *)ksp;
396 mutex_enter(&kstat_chain_lock);
397 ASSERT(e->e_owner == curthread);
398 e->e_owner = NULL;
399 cv_broadcast(&e->e_cv);
400 mutex_exit(&kstat_chain_lock);
403 kstat_t *
404 kstat_hold_bykid(kid_t kid, zoneid_t zoneid)
406 ekstat_t e;
408 e.e_ks.ks_kid = kid;
409 e.e_zone.zoneid = zoneid;
410 e.e_zone.next = NULL;
412 return (kstat_hold(&kstat_avl_bykid, &e));
415 kstat_t *
416 kstat_hold_byname(const char *ks_module, int ks_instance, const char *ks_name,
417 zoneid_t ks_zoneid)
419 ekstat_t e;
421 kstat_set_string(e.e_ks.ks_module, ks_module);
422 e.e_ks.ks_instance = ks_instance;
423 kstat_set_string(e.e_ks.ks_name, ks_name);
424 e.e_zone.zoneid = ks_zoneid;
425 e.e_zone.next = NULL;
426 return (kstat_hold(&kstat_avl_byname, &e));
429 static ekstat_t *
430 kstat_alloc(size_t size)
432 ekstat_t *e = NULL;
434 size = P2ROUNDUP(sizeof (ekstat_t) + size, KSTAT_ALIGN);
436 if (kstat_arena == NULL) {
437 if (size <= kstat_initial_avail) {
438 e = kstat_initial_ptr;
439 kstat_initial_ptr = (char *)kstat_initial_ptr + size;
440 kstat_initial_avail -= size;
442 } else {
443 e = vmem_alloc(kstat_arena, size, VM_NOSLEEP);
446 if (e != NULL) {
447 bzero(e, size);
448 e->e_size = size;
449 cv_init(&e->e_cv, NULL, CV_DEFAULT, NULL);
452 return (e);
455 static void
456 kstat_free(ekstat_t *e)
458 cv_destroy(&e->e_cv);
459 vmem_free(kstat_arena, e, e->e_size);
463 * Create various system kstats.
465 void
466 kstat_init(void)
468 kstat_t *ksp;
469 ekstat_t *e;
470 avl_tree_t *t = &kstat_avl_bykid;
473 * Set up the kstat vmem arena.
475 kstat_arena = vmem_create("kstat",
476 kstat_initial, sizeof (kstat_initial), KSTAT_ALIGN,
477 segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
480 * Make initial kstats appear as though they were allocated.
482 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER))
483 (void) vmem_xalloc(kstat_arena, e->e_size, KSTAT_ALIGN,
484 0, 0, e, (char *)e + e->e_size,
485 VM_NOSLEEP | VM_BESTFIT | VM_PANIC);
488 * The mother of all kstats. The first kstat in the system, which
489 * always has KID 0, has the headers for all kstats (including itself)
490 * as its data. Thus, the kstat driver does not need any special
491 * interface to extract the kstat chain.
493 kstat_chain_id = 0;
494 ksp = kstat_create("unix", 0, "kstat_headers", "kstat", KSTAT_TYPE_RAW,
495 0, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE);
496 if (ksp) {
497 ksp->ks_lock = &kstat_chain_lock;
498 ksp->ks_update = header_kstat_update;
499 ksp->ks_snapshot = header_kstat_snapshot;
500 kstat_install(ksp);
501 } else {
502 panic("cannot create kstat 'kstat_headers'");
505 ksp = kstat_create("unix", 0, "kstat_types", "kstat",
506 KSTAT_TYPE_NAMED, KSTAT_NUM_TYPES, 0);
507 if (ksp) {
508 int i;
509 kstat_named_t *kn = KSTAT_NAMED_PTR(ksp);
511 for (i = 0; i < KSTAT_NUM_TYPES; i++) {
512 kstat_named_init(&kn[i], kstat_data_type[i].name,
513 KSTAT_DATA_ULONG);
514 kn[i].value.ul = i;
516 kstat_install(ksp);
519 ksp = kstat_create("unix", 0, "sysinfo", "misc", KSTAT_TYPE_RAW,
520 sizeof (sysinfo_t), KSTAT_FLAG_VIRTUAL);
521 if (ksp) {
522 ksp->ks_data = (void *) &sysinfo;
523 kstat_install(ksp);
526 ksp = kstat_create("unix", 0, "vminfo", "vm", KSTAT_TYPE_RAW,
527 sizeof (vminfo_t), KSTAT_FLAG_VIRTUAL);
528 if (ksp) {
529 ksp->ks_data = (void *) &vminfo;
530 kstat_install(ksp);
533 ksp = kstat_create("unix", 0, "segmap", "vm", KSTAT_TYPE_NAMED,
534 segmapcnt_ndata, KSTAT_FLAG_VIRTUAL);
535 if (ksp) {
536 ksp->ks_data = (void *) segmapcnt_ptr;
537 ksp->ks_update = segmap_kstat_update;
538 kstat_install(ksp);
541 ksp = kstat_create("unix", 0, "biostats", "misc", KSTAT_TYPE_NAMED,
542 biostats_ndata, KSTAT_FLAG_VIRTUAL);
543 if (ksp) {
544 ksp->ks_data = (void *) biostats_ptr;
545 kstat_install(ksp);
548 ksp = kstat_create("unix", 0, "var", "misc", KSTAT_TYPE_RAW,
549 sizeof (struct var), KSTAT_FLAG_VIRTUAL);
550 if (ksp) {
551 ksp->ks_data = (void *) &v;
552 kstat_install(ksp);
555 ksp = kstat_create("unix", 0, "system_misc", "misc", KSTAT_TYPE_NAMED,
556 sizeof (system_misc_kstat) / sizeof (kstat_named_t),
557 KSTAT_FLAG_VIRTUAL);
558 if (ksp) {
559 ksp->ks_data = (void *) &system_misc_kstat;
560 ksp->ks_update = system_misc_kstat_update;
561 kstat_install(ksp);
564 ksp = kstat_create("unix", 0, "system_pages", "pages", KSTAT_TYPE_NAMED,
565 sizeof (system_pages_kstat) / sizeof (kstat_named_t),
566 KSTAT_FLAG_VIRTUAL);
567 if (ksp) {
568 ksp->ks_data = (void *) &system_pages_kstat;
569 ksp->ks_update = system_pages_kstat_update;
570 kstat_install(ksp);
573 ksp = kstat_create("poll", 0, "pollstats", "misc", KSTAT_TYPE_NAMED,
574 pollstats_ndata, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
576 if (ksp) {
577 ksp->ks_data = pollstats_ptr;
578 kstat_install(ksp);
583 * Caller of this should ensure that the string pointed by src
584 * doesn't change while kstat's lock is held. Not doing so defeats
585 * kstat's snapshot strategy as explained in <sys/kstat.h>
587 void
588 kstat_named_setstr(kstat_named_t *knp, const char *src)
590 if (knp->data_type != KSTAT_DATA_STRING)
591 panic("kstat_named_setstr('%p', '%p'): "
592 "named kstat is not of type KSTAT_DATA_STRING",
593 (void *)knp, (void *)src);
595 KSTAT_NAMED_STR_PTR(knp) = (char *)src;
596 if (src != NULL)
597 KSTAT_NAMED_STR_BUFLEN(knp) = strlen(src) + 1;
598 else
599 KSTAT_NAMED_STR_BUFLEN(knp) = 0;
602 void
603 kstat_set_string(char *dst, const char *src)
605 bzero(dst, KSTAT_STRLEN);
606 (void) strncpy(dst, src, KSTAT_STRLEN - 1);
609 void
610 kstat_named_init(kstat_named_t *knp, const char *name, uchar_t data_type)
612 kstat_set_string(knp->name, name);
613 knp->data_type = data_type;
615 if (data_type == KSTAT_DATA_STRING)
616 kstat_named_setstr(knp, NULL);
619 void
620 kstat_timer_init(kstat_timer_t *ktp, const char *name)
622 kstat_set_string(ktp->name, name);
625 /* ARGSUSED */
626 static int
627 default_kstat_update(kstat_t *ksp, int rw)
629 uint_t i;
630 size_t len = 0;
631 kstat_named_t *knp;
634 * Named kstats with variable-length long strings have a standard
635 * way of determining how much space is needed to hold the snapshot:
637 if (ksp->ks_data != NULL && ksp->ks_type == KSTAT_TYPE_NAMED &&
638 (ksp->ks_flags & KSTAT_FLAG_VAR_SIZE)) {
641 * Add in the space required for the strings
643 knp = KSTAT_NAMED_PTR(ksp);
644 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
645 if (knp->data_type == KSTAT_DATA_STRING)
646 len += KSTAT_NAMED_STR_BUFLEN(knp);
648 ksp->ks_data_size =
649 ksp->ks_ndata * sizeof (kstat_named_t) + len;
651 return (0);
654 static int
655 default_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
657 kstat_io_t *kiop;
658 hrtime_t cur_time;
659 size_t namedsz;
661 ksp->ks_snaptime = cur_time = gethrtime();
663 if (rw == KSTAT_WRITE) {
664 if (!(ksp->ks_flags & KSTAT_FLAG_WRITABLE))
665 return (EACCES);
666 bcopy(buf, ksp->ks_data, ksp->ks_data_size);
667 return (0);
671 * KSTAT_TYPE_NAMED kstats are defined to have ks_ndata
672 * number of kstat_named_t structures, followed by an optional
673 * string segment. The ks_data generally holds only the
674 * kstat_named_t structures. So we copy it first. The strings,
675 * if any, are copied below. For other kstat types, ks_data holds the
676 * entire buffer.
679 namedsz = sizeof (kstat_named_t) * ksp->ks_ndata;
680 if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data_size > namedsz)
681 bcopy(ksp->ks_data, buf, namedsz);
682 else
683 bcopy(ksp->ks_data, buf, ksp->ks_data_size);
686 * Apply kstat type-specific data massaging
688 switch (ksp->ks_type) {
690 case KSTAT_TYPE_IO:
692 * Normalize time units and deal with incomplete transactions
694 kiop = (kstat_io_t *)buf;
696 scalehrtime(&kiop->wtime);
697 scalehrtime(&kiop->wlentime);
698 scalehrtime(&kiop->wlastupdate);
699 scalehrtime(&kiop->rtime);
700 scalehrtime(&kiop->rlentime);
701 scalehrtime(&kiop->rlastupdate);
703 if (kiop->wcnt != 0) {
704 /* like kstat_waitq_exit */
705 hrtime_t wfix = cur_time - kiop->wlastupdate;
706 kiop->wlastupdate = cur_time;
707 kiop->wlentime += kiop->wcnt * wfix;
708 kiop->wtime += wfix;
711 if (kiop->rcnt != 0) {
712 /* like kstat_runq_exit */
713 hrtime_t rfix = cur_time - kiop->rlastupdate;
714 kiop->rlastupdate = cur_time;
715 kiop->rlentime += kiop->rcnt * rfix;
716 kiop->rtime += rfix;
718 break;
720 case KSTAT_TYPE_NAMED:
722 * Massage any long strings in at the end of the buffer
724 if (ksp->ks_data_size > namedsz) {
725 uint_t i;
726 kstat_named_t *knp = buf;
727 char *dst = (char *)(knp + ksp->ks_ndata);
729 * Copy strings and update pointers
731 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
732 if (knp->data_type == KSTAT_DATA_STRING &&
733 KSTAT_NAMED_STR_PTR(knp) != NULL) {
734 bcopy(KSTAT_NAMED_STR_PTR(knp), dst,
735 KSTAT_NAMED_STR_BUFLEN(knp));
736 KSTAT_NAMED_STR_PTR(knp) = dst;
737 dst += KSTAT_NAMED_STR_BUFLEN(knp);
740 ASSERT(dst <= ((char *)buf + ksp->ks_data_size));
742 break;
744 return (0);
747 static int
748 header_kstat_update(kstat_t *header_ksp, int rw)
750 int nkstats = 0;
751 ekstat_t *e;
752 avl_tree_t *t = &kstat_avl_bykid;
753 zoneid_t zoneid;
755 if (rw == KSTAT_WRITE)
756 return (EACCES);
758 ASSERT(MUTEX_HELD(&kstat_chain_lock));
760 zoneid = getzoneid();
761 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
762 if (kstat_zone_find((kstat_t *)e, zoneid) &&
763 (e->e_ks.ks_flags & KSTAT_FLAG_INVALID) == 0) {
764 nkstats++;
767 header_ksp->ks_ndata = nkstats;
768 header_ksp->ks_data_size = nkstats * sizeof (kstat_t);
769 return (0);
773 * Copy out the data section of kstat 0, which consists of the list
774 * of all kstat headers. By specification, these headers must be
775 * copied out in order of increasing KID.
777 static int
778 header_kstat_snapshot(kstat_t *header_ksp, void *buf, int rw)
780 ekstat_t *e;
781 avl_tree_t *t = &kstat_avl_bykid;
782 zoneid_t zoneid;
784 header_ksp->ks_snaptime = gethrtime();
786 if (rw == KSTAT_WRITE)
787 return (EACCES);
789 ASSERT(MUTEX_HELD(&kstat_chain_lock));
791 zoneid = getzoneid();
792 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
793 if (kstat_zone_find((kstat_t *)e, zoneid) &&
794 (e->e_ks.ks_flags & KSTAT_FLAG_INVALID) == 0) {
795 bcopy(&e->e_ks, buf, sizeof (kstat_t));
796 buf = (char *)buf + sizeof (kstat_t);
800 return (0);
803 /* ARGSUSED */
804 static int
805 system_misc_kstat_update(kstat_t *ksp, int rw)
807 int myncpus = ncpus;
808 int *loadavgp = &avenrun[0];
809 int loadavg[LOADAVG_NSTATS];
810 time_t zone_boot_time;
811 clock_t zone_lbolt;
812 hrtime_t zone_hrtime;
813 size_t zone_nproc;
815 if (rw == KSTAT_WRITE)
816 return (EACCES);
818 if (!INGLOBALZONE(curproc)) {
820 * Here we grab cpu_lock which is OK as long as no-one in the
821 * future attempts to lookup this particular kstat
822 * (unix:0:system_misc) while holding cpu_lock.
824 mutex_enter(&cpu_lock);
825 if (pool_pset_enabled()) {
826 psetid_t mypsid = zone_pset_get(curproc->p_zone);
827 int error;
829 myncpus = zone_ncpus_get(curproc->p_zone);
830 ASSERT(myncpus > 0);
831 error = cpupart_get_loadavg(mypsid, &loadavg[0],
832 LOADAVG_NSTATS);
833 ASSERT(error == 0);
834 loadavgp = &loadavg[0];
836 mutex_exit(&cpu_lock);
839 if (INGLOBALZONE(curproc)) {
840 zone_boot_time = boot_time;
841 zone_lbolt = ddi_get_lbolt();
842 zone_nproc = nproc;
843 } else {
844 zone_boot_time = curproc->p_zone->zone_boot_time;
846 zone_hrtime = gethrtime();
847 zone_lbolt = (clock_t)(NSEC_TO_TICK(zone_hrtime) -
848 NSEC_TO_TICK(curproc->p_zone->zone_zsched->p_mstart));
849 mutex_enter(&curproc->p_zone->zone_nlwps_lock);
850 zone_nproc = curproc->p_zone->zone_nprocs;
851 mutex_exit(&curproc->p_zone->zone_nlwps_lock);
854 system_misc_kstat.ncpus.value.ui32 = (uint32_t)myncpus;
855 system_misc_kstat.lbolt.value.ui32 = (uint32_t)zone_lbolt;
856 system_misc_kstat.deficit.value.ui32 = (uint32_t)deficit;
857 system_misc_kstat.clk_intr.value.ui32 = (uint32_t)zone_lbolt;
858 system_misc_kstat.vac.value.ui32 = (uint32_t)vac;
859 system_misc_kstat.nproc.value.ui32 = (uint32_t)zone_nproc;
860 system_misc_kstat.avenrun_1min.value.ui32 = (uint32_t)loadavgp[0];
861 system_misc_kstat.avenrun_5min.value.ui32 = (uint32_t)loadavgp[1];
862 system_misc_kstat.avenrun_15min.value.ui32 = (uint32_t)loadavgp[2];
863 system_misc_kstat.boot_time.value.ui32 = (uint32_t)
864 zone_boot_time;
865 return (0);
868 #ifdef __sparc
869 extern caddr_t econtig32;
870 #else /* !__sparc */
871 extern caddr_t econtig;
872 #endif /* __sparc */
874 /* ARGSUSED */
875 static int
876 system_pages_kstat_update(kstat_t *ksp, int rw)
878 kobj_stat_t kobj_stat;
880 if (rw == KSTAT_WRITE) {
881 return (EACCES);
884 kobj_stat_get(&kobj_stat);
885 system_pages_kstat.physmem.value.ul = (ulong_t)physmem;
886 system_pages_kstat.nalloc.value.ul = kobj_stat.nalloc;
887 system_pages_kstat.nfree.value.ul = kobj_stat.nfree;
888 system_pages_kstat.nalloc_calls.value.ul = kobj_stat.nalloc_calls;
889 system_pages_kstat.nfree_calls.value.ul = kobj_stat.nfree_calls;
890 system_pages_kstat.kernelbase.value.ul = (ulong_t)KERNELBASE;
892 #ifdef __sparc
894 * kstat should REALLY be modified to also report kmem64_base and
895 * kmem64_end (see sun4u/os/startup.c), as the virtual address range
896 * [ kernelbase .. econtig ] no longer is truly reflective of the
897 * kernel's vallocs...
899 system_pages_kstat.econtig.value.ul = (ulong_t)econtig32;
900 #else /* !__sparc */
901 system_pages_kstat.econtig.value.ul = (ulong_t)econtig;
902 #endif /* __sparc */
904 system_pages_kstat.freemem.value.ul = (ulong_t)freemem;
905 system_pages_kstat.availrmem.value.ul = (ulong_t)availrmem;
906 system_pages_kstat.lotsfree.value.ul = (ulong_t)lotsfree;
907 system_pages_kstat.desfree.value.ul = (ulong_t)desfree;
908 system_pages_kstat.minfree.value.ul = (ulong_t)minfree;
909 system_pages_kstat.fastscan.value.ul = (ulong_t)fastscan;
910 system_pages_kstat.slowscan.value.ul = (ulong_t)slowscan;
911 system_pages_kstat.nscan.value.ul = (ulong_t)nscan;
912 system_pages_kstat.desscan.value.ul = (ulong_t)desscan;
913 system_pages_kstat.pagesfree.value.ul = (ulong_t)freemem;
914 system_pages_kstat.pageslocked.value.ul = (ulong_t)(availrmem_initial -
915 availrmem);
916 system_pages_kstat.pagestotal.value.ul = (ulong_t)total_pages;
918 * pp_kernel represents total pages used by the kernel since the
919 * startup. This formula takes into account the boottime kernel
920 * footprint and also considers the availrmem changes because of
921 * user explicit page locking.
923 system_pages_kstat.pp_kernel.value.ul = (ulong_t)(physinstalled -
924 obp_pages - availrmem - k_anoninfo.ani_mem_resv -
925 anon_segkp_pages_locked - pages_locked -
926 pages_claimed - pages_useclaim);
928 return (0);
931 kstat_t *
932 kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
933 const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags)
935 return (kstat_create_zone(ks_module, ks_instance, ks_name, ks_class,
936 ks_type, ks_ndata, ks_flags, ALL_ZONES));
940 * Allocate and initialize a kstat structure. Or, if a dormant kstat with
941 * the specified name exists, reactivate it. Returns a pointer to the kstat
942 * on success, NULL on failure. The kstat will not be visible to the
943 * kstat driver until kstat_install().
945 kstat_t *
946 kstat_create_zone(const char *ks_module, int ks_instance, const char *ks_name,
947 const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
948 zoneid_t ks_zoneid)
950 size_t ks_data_size;
951 kstat_t *ksp;
952 ekstat_t *e;
953 avl_index_t where;
954 char namebuf[KSTAT_STRLEN + 16];
956 if (avl_numnodes(&kstat_avl_bykid) == 0) {
957 avl_create(&kstat_avl_bykid, kstat_compare_bykid,
958 sizeof (ekstat_t), offsetof(struct ekstat, e_avl_bykid));
960 avl_create(&kstat_avl_byname, kstat_compare_byname,
961 sizeof (ekstat_t), offsetof(struct ekstat, e_avl_byname));
965 * If ks_name == NULL, set the ks_name to <module><instance>.
967 if (ks_name == NULL) {
968 char buf[KSTAT_STRLEN];
969 kstat_set_string(buf, ks_module);
970 (void) sprintf(namebuf, "%s%d", buf, ks_instance);
971 ks_name = namebuf;
975 * Make sure it's a valid kstat data type
977 if (ks_type >= KSTAT_NUM_TYPES) {
978 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
979 "invalid kstat type %d",
980 ks_module, ks_instance, ks_name, ks_type);
981 return (NULL);
985 * Don't allow persistent virtual kstats -- it makes no sense.
986 * ks_data points to garbage when the client goes away.
988 if ((ks_flags & KSTAT_FLAG_PERSISTENT) &&
989 (ks_flags & KSTAT_FLAG_VIRTUAL)) {
990 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
991 "cannot create persistent virtual kstat",
992 ks_module, ks_instance, ks_name);
993 return (NULL);
997 * Don't allow variable-size physical kstats, since the framework's
998 * memory allocation for physical kstat data is fixed at creation time.
1000 if ((ks_flags & KSTAT_FLAG_VAR_SIZE) &&
1001 !(ks_flags & KSTAT_FLAG_VIRTUAL)) {
1002 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1003 "cannot create variable-size physical kstat",
1004 ks_module, ks_instance, ks_name);
1005 return (NULL);
1009 * Make sure the number of data fields is within legal range
1011 if (ks_ndata < kstat_data_type[ks_type].min_ndata ||
1012 ks_ndata > kstat_data_type[ks_type].max_ndata) {
1013 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1014 "ks_ndata=%d out of range [%d, %d]",
1015 ks_module, ks_instance, ks_name, (int)ks_ndata,
1016 kstat_data_type[ks_type].min_ndata,
1017 kstat_data_type[ks_type].max_ndata);
1018 return (NULL);
1021 ks_data_size = kstat_data_type[ks_type].size * ks_ndata;
1024 * If the named kstat already exists and is dormant, reactivate it.
1026 ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
1027 if (ksp != NULL) {
1028 if (!(ksp->ks_flags & KSTAT_FLAG_DORMANT)) {
1030 * The named kstat exists but is not dormant --
1031 * this is a kstat namespace collision.
1033 kstat_rele(ksp);
1034 cmn_err(CE_WARN,
1035 "kstat_create('%s', %d, '%s'): namespace collision",
1036 ks_module, ks_instance, ks_name);
1037 return (NULL);
1039 if ((strcmp(ksp->ks_class, ks_class) != 0) ||
1040 (ksp->ks_type != ks_type) ||
1041 (ksp->ks_ndata != ks_ndata) ||
1042 (ks_flags & KSTAT_FLAG_VIRTUAL)) {
1044 * The name is the same, but the other key parameters
1045 * differ from those of the dormant kstat -- bogus.
1047 kstat_rele(ksp);
1048 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1049 "invalid reactivation of dormant kstat",
1050 ks_module, ks_instance, ks_name);
1051 return (NULL);
1054 * Return dormant kstat pointer to caller. As usual,
1055 * the kstat is marked invalid until kstat_install().
1057 ksp->ks_flags |= KSTAT_FLAG_INVALID;
1058 kstat_rele(ksp);
1059 return (ksp);
1063 * Allocate memory for the new kstat header and, if this is a physical
1064 * kstat, the data section.
1066 e = kstat_alloc(ks_flags & KSTAT_FLAG_VIRTUAL ? 0 : ks_data_size);
1067 if (e == NULL) {
1068 cmn_err(CE_NOTE, "kstat_create('%s', %d, '%s'): "
1069 "insufficient kernel memory",
1070 ks_module, ks_instance, ks_name);
1071 return (NULL);
1075 * Initialize as many fields as we can. The caller may reset
1076 * ks_lock, ks_update, ks_private, and ks_snapshot as necessary.
1077 * Creators of virtual kstats may also reset ks_data. It is
1078 * also up to the caller to initialize the kstat data section,
1079 * if necessary. All initialization must be complete before
1080 * calling kstat_install().
1082 e->e_zone.zoneid = ks_zoneid;
1083 e->e_zone.next = NULL;
1085 ksp = &e->e_ks;
1086 ksp->ks_crtime = gethrtime();
1087 kstat_set_string(ksp->ks_module, ks_module);
1088 ksp->ks_instance = ks_instance;
1089 kstat_set_string(ksp->ks_name, ks_name);
1090 ksp->ks_type = ks_type;
1091 kstat_set_string(ksp->ks_class, ks_class);
1092 ksp->ks_flags = ks_flags | KSTAT_FLAG_INVALID;
1093 if (ks_flags & KSTAT_FLAG_VIRTUAL)
1094 ksp->ks_data = NULL;
1095 else
1096 ksp->ks_data = (void *)(e + 1);
1097 ksp->ks_ndata = ks_ndata;
1098 ksp->ks_data_size = ks_data_size;
1099 ksp->ks_snaptime = ksp->ks_crtime;
1100 ksp->ks_update = default_kstat_update;
1101 ksp->ks_private = NULL;
1102 ksp->ks_snapshot = default_kstat_snapshot;
1103 ksp->ks_lock = NULL;
1105 mutex_enter(&kstat_chain_lock);
1108 * Add our kstat to the AVL trees.
1110 if (avl_find(&kstat_avl_byname, e, &where) != NULL) {
1111 mutex_exit(&kstat_chain_lock);
1112 cmn_err(CE_WARN,
1113 "kstat_create('%s', %d, '%s'): namespace collision",
1114 ks_module, ks_instance, ks_name);
1115 kstat_free(e);
1116 return (NULL);
1118 avl_insert(&kstat_avl_byname, e, where);
1121 * Loop around until we find an unused KID.
1123 do {
1124 ksp->ks_kid = kstat_chain_id++;
1125 } while (avl_find(&kstat_avl_bykid, e, &where) != NULL);
1126 avl_insert(&kstat_avl_bykid, e, where);
1128 mutex_exit(&kstat_chain_lock);
1130 return (ksp);
1134 * Activate a fully initialized kstat and make it visible to /dev/kstat.
1136 void
1137 kstat_install(kstat_t *ksp)
1139 zoneid_t zoneid = ((ekstat_t *)ksp)->e_zone.zoneid;
1142 * If this is a variable-size kstat, it MUST provide kstat data locking
1143 * to prevent data-size races with kstat readers.
1145 if ((ksp->ks_flags & KSTAT_FLAG_VAR_SIZE) && ksp->ks_lock == NULL) {
1146 panic("kstat_install('%s', %d, '%s'): "
1147 "cannot create variable-size kstat without data lock",
1148 ksp->ks_module, ksp->ks_instance, ksp->ks_name);
1151 if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
1152 cmn_err(CE_WARN, "kstat_install(%p): does not exist",
1153 (void *)ksp);
1154 return;
1157 if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data != NULL) {
1158 int has_long_strings = 0;
1159 uint_t i;
1160 kstat_named_t *knp = KSTAT_NAMED_PTR(ksp);
1162 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
1163 if (knp->data_type == KSTAT_DATA_STRING) {
1164 has_long_strings = 1;
1165 break;
1169 * It is an error for a named kstat with fields of
1170 * KSTAT_DATA_STRING to be non-virtual.
1172 if (has_long_strings && !(ksp->ks_flags & KSTAT_FLAG_VIRTUAL)) {
1173 panic("kstat_install('%s', %d, '%s'): "
1174 "named kstat containing KSTAT_DATA_STRING "
1175 "is not virtual",
1176 ksp->ks_module, ksp->ks_instance,
1177 ksp->ks_name);
1180 * The default snapshot routine does not handle KSTAT_WRITE
1181 * for long strings.
1183 if (has_long_strings && (ksp->ks_flags & KSTAT_FLAG_WRITABLE) &&
1184 (ksp->ks_snapshot == default_kstat_snapshot)) {
1185 panic("kstat_install('%s', %d, '%s'): "
1186 "named kstat containing KSTAT_DATA_STRING "
1187 "is writable but uses default snapshot routine",
1188 ksp->ks_module, ksp->ks_instance, ksp->ks_name);
1192 if (ksp->ks_flags & KSTAT_FLAG_DORMANT) {
1195 * We are reactivating a dormant kstat. Initialize the
1196 * caller's underlying data to the value it had when the
1197 * kstat went dormant, and mark the kstat as active.
1198 * Grab the provider's kstat lock if it's not already held.
1200 kmutex_t *lp = ksp->ks_lock;
1201 if (lp != NULL && MUTEX_NOT_HELD(lp)) {
1202 mutex_enter(lp);
1203 (void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
1204 mutex_exit(lp);
1205 } else {
1206 (void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
1208 ksp->ks_flags &= ~KSTAT_FLAG_DORMANT;
1212 * Now that the kstat is active, make it visible to the kstat driver.
1214 ksp->ks_flags &= ~KSTAT_FLAG_INVALID;
1215 kstat_rele(ksp);
1219 * Remove a kstat from the system. Or, if it's a persistent kstat,
1220 * just update the data and mark it as dormant.
1222 void
1223 kstat_delete(kstat_t *ksp)
1225 kmutex_t *lp;
1226 ekstat_t *e = (ekstat_t *)ksp;
1227 zoneid_t zoneid;
1228 kstat_zone_t *kz;
1230 ASSERT(ksp != NULL);
1232 if (ksp == NULL)
1233 return;
1235 zoneid = e->e_zone.zoneid;
1237 lp = ksp->ks_lock;
1239 if (lp != NULL && MUTEX_HELD(lp)) {
1240 panic("kstat_delete(%p): caller holds data lock %p",
1241 (void *)ksp, (void *)lp);
1244 if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
1245 cmn_err(CE_WARN, "kstat_delete(%p): does not exist",
1246 (void *)ksp);
1247 return;
1250 if (ksp->ks_flags & KSTAT_FLAG_PERSISTENT) {
1252 * Update the data one last time, so that all activity
1253 * prior to going dormant has been accounted for.
1255 KSTAT_ENTER(ksp);
1256 (void) KSTAT_UPDATE(ksp, KSTAT_READ);
1257 KSTAT_EXIT(ksp);
1260 * Mark the kstat as dormant and restore caller-modifiable
1261 * fields to default values, so the kstat is readable during
1262 * the dormant phase.
1264 ksp->ks_flags |= KSTAT_FLAG_DORMANT;
1265 ksp->ks_lock = NULL;
1266 ksp->ks_update = default_kstat_update;
1267 ksp->ks_private = NULL;
1268 ksp->ks_snapshot = default_kstat_snapshot;
1269 kstat_rele(ksp);
1270 return;
1274 * Remove the kstat from the framework's AVL trees,
1275 * free the allocated memory, and increment kstat_chain_id so
1276 * /dev/kstat clients can detect the event.
1278 mutex_enter(&kstat_chain_lock);
1279 avl_remove(&kstat_avl_bykid, e);
1280 avl_remove(&kstat_avl_byname, e);
1281 kstat_chain_id++;
1282 mutex_exit(&kstat_chain_lock);
1284 kz = e->e_zone.next;
1285 while (kz != NULL) {
1286 kstat_zone_t *t = kz;
1288 kz = kz->next;
1289 kmem_free(t, sizeof (*t));
1291 kstat_rele(ksp);
1292 kstat_free(e);
1295 void
1296 kstat_delete_byname_zone(const char *ks_module, int ks_instance,
1297 const char *ks_name, zoneid_t ks_zoneid)
1299 kstat_t *ksp;
1301 ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
1302 if (ksp != NULL) {
1303 kstat_rele(ksp);
1304 kstat_delete(ksp);
1308 void
1309 kstat_delete_byname(const char *ks_module, int ks_instance, const char *ks_name)
1311 kstat_delete_byname_zone(ks_module, ks_instance, ks_name, ALL_ZONES);
1315 * The sparc V9 versions of these routines can be much cheaper than
1316 * the poor 32-bit compiler can comprehend, so they're in sparcv9_subr.s.
1317 * For simplicity, however, we always feed the C versions to lint.
1319 #if !defined(__sparc) || defined(lint) || defined(__lint)
1321 void
1322 kstat_waitq_enter(kstat_io_t *kiop)
1324 hrtime_t new, delta;
1325 ulong_t wcnt;
1327 new = gethrtime_unscaled();
1328 delta = new - kiop->wlastupdate;
1329 kiop->wlastupdate = new;
1330 wcnt = kiop->wcnt++;
1331 if (wcnt != 0) {
1332 kiop->wlentime += delta * wcnt;
1333 kiop->wtime += delta;
1337 void
1338 kstat_waitq_exit(kstat_io_t *kiop)
1340 hrtime_t new, delta;
1341 ulong_t wcnt;
1343 new = gethrtime_unscaled();
1344 delta = new - kiop->wlastupdate;
1345 kiop->wlastupdate = new;
1346 wcnt = kiop->wcnt--;
1347 ASSERT((int)wcnt > 0);
1348 kiop->wlentime += delta * wcnt;
1349 kiop->wtime += delta;
1352 void
1353 kstat_runq_enter(kstat_io_t *kiop)
1355 hrtime_t new, delta;
1356 ulong_t rcnt;
1358 new = gethrtime_unscaled();
1359 delta = new - kiop->rlastupdate;
1360 kiop->rlastupdate = new;
1361 rcnt = kiop->rcnt++;
1362 if (rcnt != 0) {
1363 kiop->rlentime += delta * rcnt;
1364 kiop->rtime += delta;
1368 void
1369 kstat_runq_exit(kstat_io_t *kiop)
1371 hrtime_t new, delta;
1372 ulong_t rcnt;
1374 new = gethrtime_unscaled();
1375 delta = new - kiop->rlastupdate;
1376 kiop->rlastupdate = new;
1377 rcnt = kiop->rcnt--;
1378 ASSERT((int)rcnt > 0);
1379 kiop->rlentime += delta * rcnt;
1380 kiop->rtime += delta;
1383 void
1384 kstat_waitq_to_runq(kstat_io_t *kiop)
1386 hrtime_t new, delta;
1387 ulong_t wcnt, rcnt;
1389 new = gethrtime_unscaled();
1391 delta = new - kiop->wlastupdate;
1392 kiop->wlastupdate = new;
1393 wcnt = kiop->wcnt--;
1394 ASSERT((int)wcnt > 0);
1395 kiop->wlentime += delta * wcnt;
1396 kiop->wtime += delta;
1398 delta = new - kiop->rlastupdate;
1399 kiop->rlastupdate = new;
1400 rcnt = kiop->rcnt++;
1401 if (rcnt != 0) {
1402 kiop->rlentime += delta * rcnt;
1403 kiop->rtime += delta;
1407 void
1408 kstat_runq_back_to_waitq(kstat_io_t *kiop)
1410 hrtime_t new, delta;
1411 ulong_t wcnt, rcnt;
1413 new = gethrtime_unscaled();
1415 delta = new - kiop->rlastupdate;
1416 kiop->rlastupdate = new;
1417 rcnt = kiop->rcnt--;
1418 ASSERT((int)rcnt > 0);
1419 kiop->rlentime += delta * rcnt;
1420 kiop->rtime += delta;
1422 delta = new - kiop->wlastupdate;
1423 kiop->wlastupdate = new;
1424 wcnt = kiop->wcnt++;
1425 if (wcnt != 0) {
1426 kiop->wlentime += delta * wcnt;
1427 kiop->wtime += delta;
1431 #endif
1433 void
1434 kstat_timer_start(kstat_timer_t *ktp)
1436 ktp->start_time = gethrtime();
1439 void
1440 kstat_timer_stop(kstat_timer_t *ktp)
1442 hrtime_t etime;
1443 u_longlong_t num_events;
1445 ktp->stop_time = etime = gethrtime();
1446 etime -= ktp->start_time;
1447 num_events = ktp->num_events;
1448 if (etime < ktp->min_time || num_events == 0)
1449 ktp->min_time = etime;
1450 if (etime > ktp->max_time)
1451 ktp->max_time = etime;
1452 ktp->elapsed_time += etime;
1453 ktp->num_events = num_events + 1;