41#include <sys/limits.h>
42#include <sys/malloc.h>
45#if defined(DIAGNOSTIC)
49#include <sys/stddef.h>
50#include <sys/stdint.h>
54#include <sys/kernel.h>
56#include <sys/rwlock.h>
57#include <sys/sysctl.h>
69 struct voistatdata_numeric
prev;
72#define VS_VSDVALID 0x0001
83#define VS_INCERRS(vs) do { \
84 if ((vs)->errs < (1U << VS_EBITS) - 1) \
95#define VOI_REQSTATE 0x0001
128 offsetof(
struct statsblob,
opaque),
129 "statsblobv1 ABI mismatch");
146 struct statsblob_tpl *
tpl;
152 stats_blob_visitcb_t
cb;
163#define TPL_LIST_RLOCK() rw_rlock(&tpllistlock)
164#define TPL_LIST_RUNLOCK() rw_runlock(&tpllistlock)
165#define TPL_LIST_WLOCK() rw_wlock(&tpllistlock)
166#define TPL_LIST_WUNLOCK() rw_wunlock(&tpllistlock)
167#define TPL_LIST_LOCK_ASSERT() rw_assert(&tpllistlock, RA_LOCKED)
168#define TPL_LIST_RLOCK_ASSERT() rw_assert(&tpllistlock, RA_RLOCKED)
169#define TPL_LIST_WLOCK_ASSERT() rw_assert(&tpllistlock, RA_WLOCKED)
170MALLOC_DEFINE(M_STATS,
"stats(9) related memory",
"stats(9) related memory");
171#define stats_free(ptr) free((ptr), M_STATS)
173static void stats_constructor(
void);
174static void stats_destructor(
void);
176#define TPL_LIST_UNLOCK() pthread_rwlock_unlock(&tpllistlock)
177#define TPL_LIST_RLOCK() pthread_rwlock_rdlock(&tpllistlock)
178#define TPL_LIST_RUNLOCK() TPL_LIST_UNLOCK()
179#define TPL_LIST_WLOCK() pthread_rwlock_wrlock(&tpllistlock)
180#define TPL_LIST_WUNLOCK() TPL_LIST_UNLOCK()
181#define TPL_LIST_LOCK_ASSERT() do { } while (0)
182#define TPL_LIST_RLOCK_ASSERT() do { } while (0)
183#define TPL_LIST_WLOCK_ASSERT() do { } while (0)
185#define KASSERT(cond, msg) do {} while (0)
186#define stats_abort() do {} while (0)
188#define KASSERT(cond, msg) do { \
193#define stats_abort() abort()
195#define stats_free(ptr) free(ptr)
196#define panic(fmt, ...) do { \
197 fprintf(stderr, (fmt), ##__VA_ARGS__); \
202#define SB_V1_MAXSZ 65535
205#define BLOB_OFFSET(sb, off) ((void *)(((uint8_t *)(sb)) + (off)))
212#define NVOIS(sb) ((int32_t)((((struct statsblobv1 *)(sb))->stats_off - \
213 sizeof(struct statsblobv1)) >> 3))
218 [VS_STYPE_VOISTATE] =
"VOISTATE",
219 [VS_STYPE_SUM] =
"SUM",
220 [VS_STYPE_MAX] =
"MAX",
221 [VS_STYPE_MIN] =
"MIN",
222 [VS_STYPE_HIST] =
"HIST",
223 [VS_STYPE_TDGST] =
"TDGST",
227 [VS_STYPE_VOISTATE] =
"VOI related state data (not a real stat)",
228 [VS_STYPE_SUM] =
"Simple arithmetic accumulator",
229 [VS_STYPE_MAX] =
"Maximum observed VOI value",
230 [VS_STYPE_MIN] =
"Minimum observed VOI value",
231 [VS_STYPE_HIST] =
"Histogram of observed VOI values",
232 [VS_STYPE_TDGST] =
"t-digest of observed VOI values",
236 [VSD_DTYPE_VOISTATE] =
"VOISTATE",
237 [VSD_DTYPE_INT_S32] =
"INT_S32",
238 [VSD_DTYPE_INT_U32] =
"INT_U32",
239 [VSD_DTYPE_INT_S64] =
"INT_S64",
240 [VSD_DTYPE_INT_U64] =
"INT_U64",
241 [VSD_DTYPE_INT_SLONG] =
"INT_SLONG",
242 [VSD_DTYPE_INT_ULONG] =
"INT_ULONG",
243 [VSD_DTYPE_Q_S32] =
"Q_S32",
244 [VSD_DTYPE_Q_U32] =
"Q_U32",
245 [VSD_DTYPE_Q_S64] =
"Q_S64",
246 [VSD_DTYPE_Q_U64] =
"Q_U64",
247 [VSD_DTYPE_CRHIST32] =
"CRHIST32",
248 [VSD_DTYPE_DRHIST32] =
"DRHIST32",
249 [VSD_DTYPE_DVHIST32] =
"DVHIST32",
250 [VSD_DTYPE_CRHIST64] =
"CRHIST64",
251 [VSD_DTYPE_DRHIST64] =
"DRHIST64",
252 [VSD_DTYPE_DVHIST64] =
"DVHIST64",
253 [VSD_DTYPE_TDGSTCLUST32] =
"TDGSTCLUST32",
254 [VSD_DTYPE_TDGSTCLUST64] =
"TDGSTCLUST64",
259 [VSD_DTYPE_INT_S32] =
sizeof(
struct voistatdata_int32),
260 [VSD_DTYPE_INT_U32] =
sizeof(
struct voistatdata_int32),
261 [VSD_DTYPE_INT_S64] =
sizeof(
struct voistatdata_int64),
262 [VSD_DTYPE_INT_U64] =
sizeof(
struct voistatdata_int64),
263 [VSD_DTYPE_INT_SLONG] =
sizeof(
struct voistatdata_intlong),
264 [VSD_DTYPE_INT_ULONG] =
sizeof(
struct voistatdata_intlong),
265 [VSD_DTYPE_Q_S32] =
sizeof(
struct voistatdata_q32),
266 [VSD_DTYPE_Q_U32] =
sizeof(
struct voistatdata_q32),
267 [VSD_DTYPE_Q_S64] =
sizeof(
struct voistatdata_q64),
268 [VSD_DTYPE_Q_U64] =
sizeof(
struct voistatdata_q64),
269 [VSD_DTYPE_CRHIST32] =
sizeof(
struct voistatdata_crhist32),
270 [VSD_DTYPE_DRHIST32] =
sizeof(
struct voistatdata_drhist32),
271 [VSD_DTYPE_DVHIST32] =
sizeof(
struct voistatdata_dvhist32),
272 [VSD_DTYPE_CRHIST64] =
sizeof(
struct voistatdata_crhist64),
273 [VSD_DTYPE_DRHIST64] =
sizeof(
struct voistatdata_drhist64),
274 [VSD_DTYPE_DVHIST64] =
sizeof(
struct voistatdata_dvhist64),
275 [VSD_DTYPE_TDGSTCLUST32] =
sizeof(
struct voistatdata_tdgstclust32),
276 [VSD_DTYPE_TDGSTCLUST64] =
sizeof(
struct voistatdata_tdgstclust64),
280 [VSD_DTYPE_VOISTATE] =
true,
281 [VSD_DTYPE_INT_S32] =
false,
282 [VSD_DTYPE_INT_U32] =
false,
283 [VSD_DTYPE_INT_S64] =
false,
284 [VSD_DTYPE_INT_U64] =
false,
285 [VSD_DTYPE_INT_SLONG] =
false,
286 [VSD_DTYPE_INT_ULONG] =
false,
287 [VSD_DTYPE_Q_S32] =
false,
288 [VSD_DTYPE_Q_U32] =
false,
289 [VSD_DTYPE_Q_S64] =
false,
290 [VSD_DTYPE_Q_U64] =
false,
291 [VSD_DTYPE_CRHIST32] =
true,
292 [VSD_DTYPE_DRHIST32] =
true,
293 [VSD_DTYPE_DVHIST32] =
true,
294 [VSD_DTYPE_CRHIST64] =
true,
295 [VSD_DTYPE_DRHIST64] =
true,
296 [VSD_DTYPE_DVHIST64] =
true,
297 [VSD_DTYPE_TDGSTCLUST32] =
true,
298 [VSD_DTYPE_TDGSTCLUST64] =
true,
303 [VSD_DTYPE_VOISTATE] = {0},
304 [VSD_DTYPE_INT_S32] = {.int32 = {.s32 = INT32_MIN}},
305 [VSD_DTYPE_INT_U32] = {.int32 = {.u32 = 0}},
306 [VSD_DTYPE_INT_S64] = {.int64 = {.s64 = INT64_MIN}},
307 [VSD_DTYPE_INT_U64] = {.int64 = {.u64 = 0}},
308 [VSD_DTYPE_INT_SLONG] = {.intlong = {.slong = LONG_MIN}},
309 [VSD_DTYPE_INT_ULONG] = {.intlong = {.ulong = 0}},
310 [VSD_DTYPE_Q_S32] = {.q32 = {.sq32 = Q_IFMINVAL(INT32_MIN)}},
311 [VSD_DTYPE_Q_U32] = {.q32 = {.uq32 = 0}},
312 [VSD_DTYPE_Q_S64] = {.q64 = {.sq64 = Q_IFMINVAL(INT64_MIN)}},
313 [VSD_DTYPE_Q_U64] = {.q64 = {.uq64 = 0}},
316 [VSD_DTYPE_VOISTATE] = {0},
317 [VSD_DTYPE_INT_S32] = {.int32 = {.s32 = INT32_MAX}},
318 [VSD_DTYPE_INT_U32] = {.int32 = {.u32 = UINT32_MAX}},
319 [VSD_DTYPE_INT_S64] = {.int64 = {.s64 = INT64_MAX}},
320 [VSD_DTYPE_INT_U64] = {.int64 = {.u64 = UINT64_MAX}},
321 [VSD_DTYPE_INT_SLONG] = {.intlong = {.slong = LONG_MAX}},
322 [VSD_DTYPE_INT_ULONG] = {.intlong = {.ulong = ULONG_MAX}},
323 [VSD_DTYPE_Q_S32] = {.q32 = {.sq32 = Q_IFMAXVAL(INT32_MAX)}},
324 [VSD_DTYPE_Q_U32] = {.q32 = {.uq32 = Q_IFMAXVAL(UINT32_MAX)}},
325 [VSD_DTYPE_Q_S64] = {.q64 = {.sq64 = Q_IFMAXVAL(INT64_MAX)}},
326 [VSD_DTYPE_Q_U64] = {.q64 = {.uq64 = Q_IFMAXVAL(UINT64_MAX)}},
334static inline void *
stats_realloc(
void *ptr,
size_t oldsz,
size_t newsz,
340 int newvoistatbytes,
int newvoistatdatabytes);
344 struct voistatdata_tdgst *tdgst, s64q_t x, uint64_t weight,
int attempt);
347ctd32cmp(
const struct voistatdata_tdgstctd32 *c1,
const struct voistatdata_tdgstctd32 *c2)
350 KASSERT(Q_PRECEQ(c1->mu, c2->mu),
351 (
"%s: Q_RELPREC(c1->mu,c2->mu)=%d", __func__,
352 Q_RELPREC(c1->mu, c2->mu)));
354 return (Q_QLTQ(c1->mu, c2->mu) ? -1 : 1);
359ctd64cmp(
const struct voistatdata_tdgstctd64 *c1,
const struct voistatdata_tdgstctd64 *c2)
362 KASSERT(Q_PRECEQ(c1->mu, c2->mu),
363 (
"%s: Q_RELPREC(c1->mu,c2->mu)=%d", __func__,
364 Q_RELPREC(c1->mu, c2->mu)));
366 return (Q_QLTQ(c1->mu, c2->mu) ? -1 : 1);
371RB_GENERATE_STATIC(rbctdth32, voistatdata_tdgstctd32, rblnk,
ctd32cmp);
372RB_GENERATE_STATIC(rbctdth64, voistatdata_tdgstctd64, rblnk,
ctd64cmp);
375static inline sbintime_t
385 clock_gettime(CLOCK_MONOTONIC_FAST, &tp);
398 if (!(
flags & (M_WAITOK | M_NOWAIT)))
403 if ((
flags & M_ZERO) && ptr != NULL) {
405 memset(ptr,
'\0', newsz);
406 else if (newsz > oldsz)
407 memset(
BLOB_OFFSET(ptr, oldsz),
'\0', newsz - oldsz);
422 if (!(
flags & (M_WAITOK | M_NOWAIT)))
442 tpl->mb->tplhash = hash32_str(tpl->mb->tplname, 0);
443 for (
int voi_id = 0; voi_id <
NVOIS(tpl->sb); voi_id++) {
444 if (tpl->mb->voi_meta[voi_id].name != NULL)
445 tpl->mb->tplhash = hash32_str(
446 tpl->mb->voi_meta[voi_id].name, tpl->mb->tplhash);
448 tpl->mb->tplhash = hash32_buf(tpl->sb, tpl->sb->cursz,
452static inline uint64_t
469 struct voistatdata_numeric *bkt_lb,
struct voistatdata_numeric *bkt_ub)
474 switch (info->scheme) {
476 step = info->lin.stepinc;
480 info->exp.stepexp + curbkt);
484 uint64_t curstepexp = 1;
486 switch (info->voi_dtype) {
487 case VSD_DTYPE_INT_S32:
489 curstepexp) <= bkt_lb->int32.s32)
492 case VSD_DTYPE_INT_U32:
494 curstepexp) <= bkt_lb->int32.u32)
497 case VSD_DTYPE_INT_S64:
499 curstepexp) <= bkt_lb->int64.s64)
502 case VSD_DTYPE_INT_U64:
504 curstepexp) <= bkt_lb->int64.u64)
507 case VSD_DTYPE_INT_SLONG:
509 curstepexp) <= bkt_lb->intlong.slong)
512 case VSD_DTYPE_INT_ULONG:
514 curstepexp) <= bkt_lb->intlong.ulong)
517 case VSD_DTYPE_Q_S32:
519 curstepexp) <= Q_GIVAL(bkt_lb->q32.sq32))
521 case VSD_DTYPE_Q_U32:
523 curstepexp) <= Q_GIVAL(bkt_lb->q32.uq32))
525 case VSD_DTYPE_Q_S64:
527 curstepexp) <= Q_GIVAL(bkt_lb->q64.sq64))
530 case VSD_DTYPE_Q_U64:
532 curstepexp) <= Q_GIVAL(bkt_lb->q64.uq64))
540 info->linexp.linstepdiv;
549 if (info->scheme == BKT_USR) {
550 *bkt_lb = info->usr.bkts[curbkt].lb;
551 *bkt_ub = info->usr.bkts[curbkt].ub;
552 }
else if (step != 0) {
553 switch (info->voi_dtype) {
554 case VSD_DTYPE_INT_S32:
555 bkt_ub->int32.s32 += (int32_t)step;
557 case VSD_DTYPE_INT_U32:
558 bkt_ub->int32.u32 += (uint32_t)step;
560 case VSD_DTYPE_INT_S64:
561 bkt_ub->int64.s64 += (int64_t)step;
563 case VSD_DTYPE_INT_U64:
564 bkt_ub->int64.u64 += (uint64_t)step;
566 case VSD_DTYPE_INT_SLONG:
567 bkt_ub->intlong.slong += (long)step;
569 case VSD_DTYPE_INT_ULONG:
570 bkt_ub->intlong.ulong += (
unsigned long)step;
572 case VSD_DTYPE_Q_S32:
573 error = Q_QADDI(&bkt_ub->q32.sq32, step);
575 case VSD_DTYPE_Q_U32:
576 error = Q_QADDI(&bkt_ub->q32.uq32, step);
578 case VSD_DTYPE_Q_S64:
579 error = Q_QADDI(&bkt_ub->q64.sq64, step);
581 case VSD_DTYPE_Q_U64:
582 error = Q_QADDI(&bkt_ub->q64.uq64, step);
597 struct voistatdata_numeric bkt_lb, bkt_ub;
601 if (info->scheme == BKT_USR) {
603 info->lb = info->usr.bkts[0].lb;
604 info->ub = info->usr.bkts[info->usr.nbkts - 1].lb;
616 if (info->scheme == BKT_USR)
617 done = (nbkts == info->usr.nbkts);
619 switch (info->voi_dtype) {
620 case VSD_DTYPE_INT_S32:
621 done = (bkt_ub.int32.s32 > info->ub.int32.s32);
623 case VSD_DTYPE_INT_U32:
624 done = (bkt_ub.int32.u32 > info->ub.int32.u32);
626 case VSD_DTYPE_INT_S64:
627 done = (bkt_ub.int64.s64 > info->ub.int64.s64);
629 case VSD_DTYPE_INT_U64:
630 done = (bkt_ub.int64.u64 > info->ub.int64.u64);
632 case VSD_DTYPE_INT_SLONG:
633 done = (bkt_ub.intlong.slong >
634 info->ub.intlong.slong);
636 case VSD_DTYPE_INT_ULONG:
637 done = (bkt_ub.intlong.ulong >
638 info->ub.intlong.ulong);
640 case VSD_DTYPE_Q_S32:
641 done = Q_QGTQ(bkt_ub.q32.sq32,
644 case VSD_DTYPE_Q_U32:
645 done = Q_QGTQ(bkt_ub.q32.uq32,
648 case VSD_DTYPE_Q_S64:
649 done = Q_QGTQ(bkt_ub.q64.sq64,
652 case VSD_DTYPE_Q_U64:
653 done = Q_QGTQ(bkt_ub.q64.uq64,
662 if (info->flags & VSD_HIST_LBOUND_INF)
664 if (info->flags & VSD_HIST_UBOUND_INF)
672 struct vss_hist_hlpr_info *info)
674 struct voistatdata_hist *hist;
675 struct voistatdata_numeric bkt_lb, bkt_ub, *lbinfbktlb, *lbinfbktub,
676 *ubinfbktlb, *ubinfbktub;
677 uint32_t bkt, nbkts, nloop;
679 if (vss == NULL || info == NULL || (info->flags &
680 (VSD_HIST_LBOUND_INF|VSD_HIST_UBOUND_INF) && (info->hist_dtype ==
681 VSD_DTYPE_DVHIST32 || info->hist_dtype == VSD_DTYPE_DVHIST64)))
684 info->voi_dtype = voi_dtype;
689 switch (info->hist_dtype) {
690 case VSD_DTYPE_CRHIST32:
691 vss->vsdsz = HIST_NBKTS2VSDSZ(crhist32, nbkts);
693 case VSD_DTYPE_DRHIST32:
694 vss->vsdsz = HIST_NBKTS2VSDSZ(drhist32, nbkts);
696 case VSD_DTYPE_DVHIST32:
697 vss->vsdsz = HIST_NBKTS2VSDSZ(dvhist32, nbkts);
699 case VSD_DTYPE_CRHIST64:
700 vss->vsdsz = HIST_NBKTS2VSDSZ(crhist64, nbkts);
702 case VSD_DTYPE_DRHIST64:
703 vss->vsdsz = HIST_NBKTS2VSDSZ(drhist64, nbkts);
705 case VSD_DTYPE_DVHIST64:
706 vss->vsdsz = HIST_NBKTS2VSDSZ(dvhist64, nbkts);
716 hist = (
struct voistatdata_hist *)vss->iv;
719 for (bkt = (info->flags & VSD_HIST_LBOUND_INF), nloop = 0;
726 switch (info->hist_dtype) {
727 case VSD_DTYPE_CRHIST32:
728 VSD(crhist32, hist)->bkts[bkt].lb = bkt_lb;
730 case VSD_DTYPE_DRHIST32:
731 VSD(drhist32, hist)->bkts[bkt].lb = bkt_lb;
732 VSD(drhist32, hist)->bkts[bkt].ub = bkt_ub;
734 case VSD_DTYPE_DVHIST32:
735 VSD(dvhist32, hist)->bkts[bkt].val = bkt_lb;
737 case VSD_DTYPE_CRHIST64:
738 VSD(crhist64, hist)->bkts[bkt].lb = bkt_lb;
740 case VSD_DTYPE_DRHIST64:
741 VSD(drhist64, hist)->bkts[bkt].lb = bkt_lb;
742 VSD(drhist64, hist)->bkts[bkt].ub = bkt_ub;
744 case VSD_DTYPE_DVHIST64:
745 VSD(dvhist64, hist)->bkts[bkt].val = bkt_lb;
752 lbinfbktlb = lbinfbktub = ubinfbktlb = ubinfbktub = NULL;
754 switch (info->hist_dtype) {
755 case VSD_DTYPE_CRHIST32:
756 lbinfbktlb = &VSD(crhist32, hist)->bkts[0].lb;
757 ubinfbktlb = &VSD(crhist32, hist)->bkts[nbkts - 1].lb;
759 case VSD_DTYPE_DRHIST32:
760 lbinfbktlb = &VSD(drhist32, hist)->bkts[0].lb;
761 lbinfbktub = &VSD(drhist32, hist)->bkts[0].ub;
762 ubinfbktlb = &VSD(drhist32, hist)->bkts[nbkts - 1].lb;
763 ubinfbktub = &VSD(drhist32, hist)->bkts[nbkts - 1].ub;
765 case VSD_DTYPE_CRHIST64:
766 lbinfbktlb = &VSD(crhist64, hist)->bkts[0].lb;
767 ubinfbktlb = &VSD(crhist64, hist)->bkts[nbkts - 1].lb;
769 case VSD_DTYPE_DRHIST64:
770 lbinfbktlb = &VSD(drhist64, hist)->bkts[0].lb;
771 lbinfbktub = &VSD(drhist64, hist)->bkts[0].ub;
772 ubinfbktlb = &VSD(drhist64, hist)->bkts[nbkts - 1].lb;
773 ubinfbktub = &VSD(drhist64, hist)->bkts[nbkts - 1].ub;
775 case VSD_DTYPE_DVHIST32:
776 case VSD_DTYPE_DVHIST64:
782 if ((info->flags & VSD_HIST_LBOUND_INF) && lbinfbktlb) {
791 if (info->voi_dtype == VSD_DTYPE_Q_S32 ||
792 info->voi_dtype == VSD_DTYPE_Q_U32) {
794 Q_SCVAL(lbinfbktlb->q32.sq32,
795 Q_GCVAL(info->lb.q32.sq32));
796 }
else if (info->voi_dtype == VSD_DTYPE_Q_S64 ||
797 info->voi_dtype == VSD_DTYPE_Q_U64) {
799 Q_SCVAL(lbinfbktlb->q64.sq64,
800 Q_GCVAL(info->lb.q64.sq64));
803 *lbinfbktub = info->lb;
805 if ((info->flags & VSD_HIST_UBOUND_INF) && ubinfbktlb) {
806 *ubinfbktlb = bkt_lb;
809 if (info->voi_dtype == VSD_DTYPE_Q_S32 ||
810 info->voi_dtype == VSD_DTYPE_Q_U32) {
811 Q_SCVAL(ubinfbktub->q32.sq32,
812 Q_GCVAL(info->lb.q32.sq32));
813 }
else if (info->voi_dtype == VSD_DTYPE_Q_S64 ||
814 info->voi_dtype == VSD_DTYPE_Q_U64) {
815 Q_SCVAL(ubinfbktub->q64.sq64,
816 Q_GCVAL(info->lb.q64.sq64));
826 struct vss_tdgst_hlpr_info *info)
828 struct voistatdata_tdgst *tdgst;
829 struct ctdth32 *ctd32tree;
830 struct ctdth64 *ctd64tree;
831 struct voistatdata_tdgstctd32 *ctd32;
832 struct voistatdata_tdgstctd64 *ctd64;
834 info->voi_dtype = voi_dtype;
836 switch (info->tdgst_dtype) {
837 case VSD_DTYPE_TDGSTCLUST32:
838 vss->vsdsz = TDGST_NCTRS2VSDSZ(tdgstclust32, info->nctds);
840 case VSD_DTYPE_TDGSTCLUST64:
841 vss->vsdsz = TDGST_NCTRS2VSDSZ(tdgstclust64, info->nctds);
851 tdgst = (
struct voistatdata_tdgst *)vss->iv;
853 switch (info->tdgst_dtype) {
854 case VSD_DTYPE_TDGSTCLUST32:
855 ctd32tree = &VSD(tdgstclust32, tdgst)->ctdtree;
856 ARB_INIT(ctd32, ctdlnk, ctd32tree, info->nctds) {
857 Q_INI(&ctd32->mu, 0, 0, info->prec);
860 case VSD_DTYPE_TDGSTCLUST64:
861 ctd64tree = &VSD(tdgstclust64, tdgst)->ctdtree;
862 ARB_INIT(ctd64, ctdlnk, ctd64tree, info->nctds) {
863 Q_INI(&ctd64->mu, 0, 0, info->prec);
875 struct vss_numeric_hlpr_info *info)
877 struct voistatdata_numeric iv;
879 switch (vss->stype) {
881 iv = stats_ctor_vsd_numeric(0);
897 vss->vs_dtype = voi_dtype;
900 case VSD_DTYPE_INT_S32:
901 *((int32_t *)vss->iv) = iv.int32.s32;
903 case VSD_DTYPE_INT_U32:
904 *((uint32_t *)vss->iv) = iv.int32.u32;
906 case VSD_DTYPE_INT_S64:
907 *((int64_t *)vss->iv) = iv.int64.s64;
909 case VSD_DTYPE_INT_U64:
910 *((uint64_t *)vss->iv) = iv.int64.u64;
912 case VSD_DTYPE_INT_SLONG:
913 *((
long *)vss->iv) = iv.intlong.slong;
915 case VSD_DTYPE_INT_ULONG:
916 *((
unsigned long *)vss->iv) = iv.intlong.ulong;
918 case VSD_DTYPE_Q_S32:
919 *((s32q_t *)vss->iv) = Q_SCVAL(iv.q32.sq32,
920 Q_CTRLINI(info->prec));
922 case VSD_DTYPE_Q_U32:
923 *((u32q_t *)vss->iv) = Q_SCVAL(iv.q32.uq32,
924 Q_CTRLINI(info->prec));
926 case VSD_DTYPE_Q_S64:
927 *((s64q_t *)vss->iv) = Q_SCVAL(iv.q64.sq64,
928 Q_CTRLINI(info->prec));
930 case VSD_DTYPE_Q_U64:
931 *((u64q_t *)vss->iv) = Q_SCVAL(iv.q64.uq64,
932 Q_CTRLINI(info->prec));
943 struct voistatspec *vss)
947 for (i = nvss - 1; i >= 0; i--) {
948 if (vss[i].hlpr && (ret = vss[i].hlpr(voi_dtype, &vss[i],
949 vss[i].hlprinfo)) != 0)
961 for (i = nvss - 1; i >= 0; i--) {
977 if (tpl_id < 0 || tpl_id >= (
int)
ntpl) {
996 for (i =
ntpl - 1; i >= 0; i--) {
998 if (strlen(
name) == strlen(
tpllist[i]->mb->tplname) &&
1000 TPL_MAX_NAME_LEN) == 0 && (!hash || hash ==
1005 }
else if (hash ==
tpllist[i]->mb->tplhash) {
1023 if (tpl_id <
ntpl) {
1024 if (
buf != NULL && len > strlen(
tpllist[tpl_id]->mb->tplname))
1025 strlcpy(
buf,
tpllist[tpl_id]->mb->tplname, len);
1037 void *seed_bytes,
size_t seed_len)
1039 uint32_t cum_pct, rnd_pct;
1055 if (seed_bytes == NULL)
1056 rnd_pct = random() / (INT32_MAX / 100);
1058 rnd_pct = hash32_buf(seed_bytes, seed_len, 0) /
1059 (UINT32_MAX / 100U);
1068 for (i = 0; i < nrates; i++) {
1069 cum_pct += rates[i].tpl_sample_pct;
1071 KASSERT(cum_pct <= 100, (
"%s cum_pct %u > 100", __func__,
1073 if (rnd_pct > cum_pct || rates[i].tpl_sample_pct == 0)
1076 return (rates[i].tpl_slot_id);
1090 if (
src == NULL || dst == NULL ||
1091 src->cursz <
sizeof(
struct statsblob) ||
1092 ((
flags & SB_CLONE_ALLOCDST) &&
1093 (
flags & (SB_CLONE_USRDSTNOFAULT | SB_CLONE_USRDST)))) {
1095 }
else if (
flags & SB_CLONE_ALLOCDST) {
1098 (*dst)->maxsz = dstmaxsz =
src->cursz;
1101 }
else if (*dst == NULL || dstmaxsz <
sizeof(
struct statsblob)) {
1106 size_t postcurszlen;
1114 if (
flags & SB_CLONE_USRDSTNOFAULT)
1116 offsetof(
struct statsblob,
maxsz));
1117 else if (
flags & SB_CLONE_USRDST)
1118 copyout(
src, *dst, offsetof(
struct statsblob,
maxsz));
1121 memcpy(*dst,
src, offsetof(
struct statsblob,
maxsz));
1123 if (dstmaxsz >=
src->cursz) {
1124 postcurszlen =
src->cursz -
1125 offsetof(
struct statsblob,
cursz);
1128 postcurszlen =
sizeof(
struct statsblob) -
1129 offsetof(struct statsblob,
cursz);
1132 if (
flags & SB_CLONE_USRDSTNOFAULT)
1135 else if (
flags & SB_CLONE_USRDST)
1136 copyout(&(
src->cursz), &((*dst)->cursz), postcurszlen);
1139 memcpy(&((*dst)->cursz), &(
src->cursz), postcurszlen);
1150 struct metablob *tpl_mb;
1153 if (
name != NULL && strlen(
name) > TPL_MAX_NAME_LEN)
1160 tpl_mb =
stats_realloc(NULL, 0,
sizeof(
struct metablob), M_ZERO);
1163 if (tpl_mb != NULL &&
name != NULL)
1166 if (tpl == NULL || tpl_sb == NULL || tpl_mb == NULL ||
1167 tpl_mb->tplname == NULL) {
1170 if (tpl_mb != NULL) {
1180 tpl_sb->
abi = STATS_ABI_V1;
1182#if BYTE_ORDER == LITTLE_ENDIAN
1184#elif BYTE_ORDER == BIG_ENDIAN
1194 (
ntpl + 1) *
sizeof(
void *), 0);
1195 if (newtpllist != NULL) {
1197 tpllist = (
struct statsblob_tpl **)newtpllist;
1198 tpllist[tpl_id] = (
struct statsblob_tpl *)tpl;
1203 if (tpl_mb != NULL) {
1216 enum vsd_dtype voi_dtype, uint32_t nvss,
struct voistatspec *vss,
1222 struct metablob *tpl_mb;
1223 int error, i, newstatdataidx, newvoibytes, newvoistatbytes,
1224 newvoistatdatabytes, newvoistatmaxid;
1227 if (voi_id < 0 || voi_dtype == 0 || voi_dtype >= VSD_NUM_DTYPES ||
1228 nvss == 0 || vss == NULL)
1231 error =
nbytes = newvoibytes = newvoistatbytes =
1232 newvoistatdatabytes = 0;
1233 newvoistatmaxid = -1;
1236 for (i = nvss - 1; i >= 0; i--) {
1237 if (vss[i].stype == 0 || vss[i].stype >= VS_NUM_STYPES ||
1238 vss[i].vs_dtype == 0 || vss[i].vs_dtype >= VSD_NUM_DTYPES ||
1239 vss[i].iv == NULL || vss[i].vsdsz == 0)
1241 if ((
int)vss[i].stype > newvoistatmaxid)
1242 newvoistatmaxid = vss[i].stype;
1243 newvoistatdatabytes += vss[i].vsdsz;
1246 if (
flags & SB_VOI_RELUPDATE) {
1250 nbytes += newvoistatdatabytes;
1253 if (tpl_id <
ntpl) {
1257 if (voi_id >=
NVOIS(tpl_sb) || tpl_sb->
vois[voi_id].
id == -1) {
1259 if (voi_id >=
NVOIS(tpl_sb)) {
1261 newvoibytes = (voi_id - (
NVOIS(tpl_sb) - 1)) *
1266 (newvoistatmaxid + 1) *
sizeof(
struct voistat);
1269 if (newvoistatmaxid >
1271 newvoistatbytes = (newvoistatmaxid -
1278 nbytes += newvoistatbytes;
1280 if (!error && newvoibytes > 0) {
1281 struct voi_meta *voi_meta = tpl_mb->voi_meta;
1284 0 :
NVOIS(tpl_sb) *
sizeof(
struct voi_meta),
1285 (1 + voi_id) *
sizeof(
struct voi_meta),
1288 if (voi_meta == NULL)
1291 tpl_mb->voi_meta = voi_meta;
1297 newvoistatbytes, newvoistatdatabytes);
1303 if (tpl_mb->voi_meta[voi_id].name == NULL)
1309 tpllist[tpl_id]->sb = (
struct statsblob *)tpl_sb;
1319 if (
flags & SB_VOI_RELUPDATE)
1342 tmpstat->
stype = VS_STYPE_VOISTATE;
1344 tmpstat->
dtype = VSD_DTYPE_VOISTATE;
1345 newstatdataidx = tmpstat->
dsz =
1346 sizeof(
struct voistatdata_numeric);
1350 for (i = 0; (uint32_t)i < nvss; i++) {
1352 (vss[i].stype *
sizeof(
struct voistat)));
1353 KASSERT(tmpstat->
stype < 0, (
"voistat %p "
1354 "already initialised", tmpstat));
1355 tmpstat->
stype = vss[i].stype;
1356 tmpstat->
flags = vss[i].flags;
1357 tmpstat->
dtype = vss[i].vs_dtype;
1358 tmpstat->
dsz = vss[i].vsdsz;
1362 vss[i].iv, vss[i].vsdsz);
1363 newstatdataidx += vss[i].vsdsz;
1386 if (tpl_id <
ntpl) {
1413 enum voi_stype stype,
enum vsd_dtype *retdtype,
struct voistatdata **retvsd,
1419 if (retvsd == NULL || sb == NULL || sb->
abi != STATS_ABI_V1 ||
1420 voi_id >=
NVOIS(sb))
1423 v = &sb->
vois[voi_id];
1429 if (retdtype != NULL)
1430 *retdtype = vs->
dtype;
1431 if (retvsdsz != NULL)
1432 *retvsdsz = vs->
dsz;
1445 if (sb == NULL || tpl_id >=
ntpl) {
1457 uint32_t
flags __unused)
1462 error = (sb->
maxsz >=
tpllist[tpl_id]->sb->cursz) ? 0 : EOVERFLOW;
1464 (
"sb %d instead of %d bytes", sb->
maxsz,
tpllist[tpl_id]->sb->cursz));
1477 int newvoistatbytes,
int newvoistatdatabytes)
1481 struct voistat *tmpvoistat, *voistat_array;
1482 int error, i, idxnewvois, idxnewvoistats,
nbytes, nvoistats;
1484 KASSERT(newvoibytes %
sizeof(
struct voi) == 0,
1485 (
"Bad newvoibytes %d", newvoibytes));
1486 KASSERT(newvoistatbytes %
sizeof(
struct voistat) == 0,
1487 (
"Bad newvoistatbytes %d", newvoistatbytes));
1489 error = ((newvoibytes %
sizeof(
struct voi) == 0) &&
1490 (newvoistatbytes %
sizeof(
struct voistat) == 0)) ? 0 : EINVAL;
1492 nbytes = newvoibytes + newvoistatbytes + newvoistatdatabytes;
1526 idxnewvois =
NVOIS(sb);
1527 idxnewvoistats = (newvoistatbytes /
sizeof(
struct voistat)) - 1;
1535 memset(&sb->
vois[idxnewvois],
'\0', newvoibytes);
1539 newvoistatdatabytes);
1542 for (i = 0; i <
NVOIS(sb); i++) {
1543 tmpvoi = &sb->
vois[i];
1544 if (i >= idxnewvois) {
1546 }
else if (tmpvoi->
id > -1) {
1556 for (i = 0; i < nvoistats; i++) {
1557 tmpvoistat = &voistat_array[i];
1558 if (i <= idxnewvoistats) {
1559 tmpvoistat->
stype = -1;
1560 }
else if (tmpvoistat->
stype > -1) {
1578 void *usrctx, uint32_t
flags)
1586 ctx.
flags = SB_IT_FIRST_CB;
1589 for (i = 0; i <
NVOIS(sb); i++) {
1593 ctx.
flags |= SB_IT_FIRST_VOISTAT;
1596 ctx.
flags |= SB_IT_FIRST_VOI;
1597 else if (i == (
NVOIS(sb) - 1))
1598 ctx.
flags |= SB_IT_LAST_VOI | SB_IT_LAST_CB;
1600 if (v->
id < 0 && (
flags & SB_IT_NULLVOI)) {
1601 if (icb(sb, v, NULL, &ctx))
1604 ctx.
flags &= ~SB_IT_FIRST_CB;
1611 if (vs->
stype < 0 &&
1612 !(
flags & SB_IT_NULLVOISTAT))
1616 ctx.
flags |= SB_IT_LAST_VOISTAT;
1617 if (i == (
NVOIS(sb) - 1))
1621 ctx.
flags &= ~SB_IT_LAST_CB;
1624 if (icb(sb, v, vs, &ctx))
1627 ctx.
flags &= ~(SB_IT_FIRST_CB | SB_IT_FIRST_VOISTAT |
1628 SB_IT_LAST_VOISTAT);
1630 ctx.
flags &= ~(SB_IT_FIRST_VOI | SB_IT_LAST_VOI);
1636 const struct voistatdata_tdgst *tdgst,
enum vsd_dtype tdgst_dtype,
1637 size_t tdgst_dsz __unused,
enum sb_str_fmt fmt,
struct sbuf *
buf,
int objdump)
1639 const struct ctdth32 *ctd32tree;
1640 const struct ctdth64 *ctd64tree;
1641 const struct voistatdata_tdgstctd32 *ctd32;
1642 const struct voistatdata_tdgstctd64 *ctd64;
1644 uint64_t smplcnt, compcnt;
1645 int is32bit, qmaxstrlen;
1646 uint16_t maxctds, curctds;
1648 switch (tdgst_dtype) {
1649 case VSD_DTYPE_TDGSTCLUST32:
1650 smplcnt = CONSTVSD(tdgstclust32, tdgst)->smplcnt;
1651 compcnt = CONSTVSD(tdgstclust32, tdgst)->compcnt;
1652 maxctds = ARB_MAXNODES(&CONSTVSD(tdgstclust32, tdgst)->ctdtree);
1653 curctds = ARB_CURNODES(&CONSTVSD(tdgstclust32, tdgst)->ctdtree);
1654 ctd32tree = &CONSTVSD(tdgstclust32, tdgst)->ctdtree;
1655 ctd32 = (objdump ? ARB_CNODE(ctd32tree, 0) :
1656 ARB_CMIN(ctdth32, ctd32tree));
1657 qmaxstrlen = (ctd32 == NULL) ? 1 : Q_MAXSTRLEN(ctd32->mu, 10);
1662 case VSD_DTYPE_TDGSTCLUST64:
1663 smplcnt = CONSTVSD(tdgstclust64, tdgst)->smplcnt;
1664 compcnt = CONSTVSD(tdgstclust64, tdgst)->compcnt;
1665 maxctds = ARB_MAXNODES(&CONSTVSD(tdgstclust64, tdgst)->ctdtree);
1666 curctds = ARB_CURNODES(&CONSTVSD(tdgstclust64, tdgst)->ctdtree);
1667 ctd64tree = &CONSTVSD(tdgstclust64, tdgst)->ctdtree;
1668 ctd64 = (objdump ? ARB_CNODE(ctd64tree, 0) :
1669 ARB_CMIN(ctdth64, ctd64tree));
1670 qmaxstrlen = (ctd64 == NULL) ? 1 : Q_MAXSTRLEN(ctd64->mu, 10);
1680 case SB_STRFMT_FREEFORM:
1681 fmtstr =
"smplcnt=%ju, compcnt=%ju, maxctds=%hu, nctds=%hu";
1683 case SB_STRFMT_JSON:
1686 "\"smplcnt\":%ju,\"compcnt\":%ju,\"maxctds\":%hu,"
1687 "\"nctds\":%hu,\"ctds\":[";
1693 while ((is32bit ? NULL != ctd32 : NULL != ctd64)) {
1694 char qstr[qmaxstrlen];
1697 case SB_STRFMT_FREEFORM:
1698 fmtstr =
"\n\t\t\t\t";
1700 case SB_STRFMT_JSON:
1709 case SB_STRFMT_FREEFORM:
1710 fmtstr =
"ctd[%hu].";
1712 case SB_STRFMT_JSON:
1714 fmtstr =
"\"ctd\":%hu,";
1718 ARB_SELFIDX(ctd32tree, ctd32) :
1719 ARB_SELFIDX(ctd64tree, ctd64));
1723 case SB_STRFMT_FREEFORM:
1726 case SB_STRFMT_JSON:
1732 Q_TOSTR((is32bit ? ctd32->mu : ctd64->mu), -1, 10, qstr,
1737 case SB_STRFMT_FREEFORM:
1738 fmtstr = is32bit ?
",cnt=%u}" :
",cnt=%ju}";
1740 case SB_STRFMT_JSON:
1742 fmtstr = is32bit ?
",\"cnt\":%u}" :
",\"cnt\":%ju}";
1746 is32bit ? ctd32->cnt : (uintmax_t)ctd64->cnt);
1749 ctd32 = (objdump ? ARB_CNODE(ctd32tree,
1750 ARB_SELFIDX(ctd32tree, ctd32) + 1) :
1751 ARB_CNEXT(ctdth32, ctd32tree, ctd32));
1753 ctd64 = (objdump ? ARB_CNODE(ctd64tree,
1754 ARB_SELFIDX(ctd64tree, ctd64) + 1) :
1755 ARB_CNEXT(ctdth64, ctd64tree, ctd64));
1757 if (fmt == SB_STRFMT_JSON &&
1758 (is32bit ? NULL != ctd32 : NULL != ctd64))
1761 if (fmt == SB_STRFMT_JSON)
1767 const struct voistatdata_hist *hist,
enum vsd_dtype hist_dtype,
1768 size_t hist_dsz,
enum sb_str_fmt fmt,
struct sbuf *
buf,
int objdump)
1770 const struct voistatdata_numeric *bkt_lb, *bkt_ub;
1775 switch (hist_dtype) {
1776 case VSD_DTYPE_CRHIST32:
1777 nbkts = HIST_VSDSZ2NBKTS(crhist32, hist_dsz);
1780 case VSD_DTYPE_DRHIST32:
1781 nbkts = HIST_VSDSZ2NBKTS(drhist32, hist_dsz);
1784 case VSD_DTYPE_DVHIST32:
1785 nbkts = HIST_VSDSZ2NBKTS(dvhist32, hist_dsz);
1788 case VSD_DTYPE_CRHIST64:
1789 nbkts = HIST_VSDSZ2NBKTS(crhist64, hist_dsz);
1792 case VSD_DTYPE_DRHIST64:
1793 nbkts = HIST_VSDSZ2NBKTS(drhist64, hist_dsz);
1796 case VSD_DTYPE_DVHIST64:
1797 nbkts = HIST_VSDSZ2NBKTS(dvhist64, hist_dsz);
1805 case SB_STRFMT_FREEFORM:
1806 fmtstr =
"nbkts=%hu, ";
1808 case SB_STRFMT_JSON:
1810 fmtstr =
"\"nbkts\":%hu,";
1816 case SB_STRFMT_FREEFORM:
1817 fmtstr = (is32bit ?
"oob=%u" :
"oob=%ju");
1819 case SB_STRFMT_JSON:
1821 fmtstr = (is32bit ?
"\"oob\":%u,\"bkts\":[" :
1822 "\"oob\":%ju,\"bkts\":[");
1826 hist_dtype, oob) : (uintmax_t)VSD_CONSTHIST_FIELDVAL(hist,
1829 for (i = 0; i < nbkts; i++) {
1830 switch (hist_dtype) {
1831 case VSD_DTYPE_CRHIST32:
1832 case VSD_DTYPE_CRHIST64:
1833 bkt_lb = VSD_CONSTCRHIST_FIELDPTR(hist, hist_dtype,
1836 bkt_ub = VSD_CONSTCRHIST_FIELDPTR(hist,
1837 hist_dtype, bkts[i + 1].lb);
1841 case VSD_DTYPE_DRHIST32:
1842 case VSD_DTYPE_DRHIST64:
1843 bkt_lb = VSD_CONSTDRHIST_FIELDPTR(hist, hist_dtype,
1845 bkt_ub = VSD_CONSTDRHIST_FIELDPTR(hist, hist_dtype,
1848 case VSD_DTYPE_DVHIST32:
1849 case VSD_DTYPE_DVHIST64:
1850 bkt_lb = bkt_ub = VSD_CONSTDVHIST_FIELDPTR(hist,
1851 hist_dtype, bkts[i].val);
1858 case SB_STRFMT_FREEFORM:
1859 fmtstr =
"\n\t\t\t\t";
1861 case SB_STRFMT_JSON:
1870 case SB_STRFMT_FREEFORM:
1871 fmtstr =
"bkt[%hu].";
1873 case SB_STRFMT_JSON:
1875 fmtstr =
"\"bkt\":%hu,";
1882 case SB_STRFMT_FREEFORM:
1885 case SB_STRFMT_JSON:
1892 voi_dtype, voi_dtype,
sizeof(
struct voistatdata_numeric),
1896 case SB_STRFMT_FREEFORM:
1899 case SB_STRFMT_JSON:
1901 fmtstr =
",\"ub\":";
1906 voi_dtype, voi_dtype,
sizeof(
struct voistatdata_numeric),
1910 case SB_STRFMT_FREEFORM:
1911 fmtstr = is32bit ?
",cnt=%u}" :
",cnt=%ju}";
1913 case SB_STRFMT_JSON:
1915 fmtstr = is32bit ?
",\"cnt\":%u}" :
",\"cnt\":%ju}";
1919 VSD_CONSTHIST_FIELDVAL(hist, hist_dtype, bkts[i].cnt) :
1920 (uintmax_t)VSD_CONSTHIST_FIELDVAL(hist, hist_dtype,
1923 if (fmt == SB_STRFMT_JSON && i < nbkts - 1)
1926 if (fmt == SB_STRFMT_JSON)
1932 enum vsd_dtype vsd_dtype,
size_t vsd_sz,
enum sb_str_fmt fmt,
1933 struct sbuf *
buf,
int objdump)
1937 if (vsd == NULL ||
buf == NULL || voi_dtype >= VSD_NUM_DTYPES ||
1938 vsd_dtype >= VSD_NUM_DTYPES || fmt >= SB_STRFMT_NUM_FMTS)
1941 switch (vsd_dtype) {
1942 case VSD_DTYPE_VOISTATE:
1944 case SB_STRFMT_FREEFORM:
1947 case SB_STRFMT_JSON:
1949 fmtstr =
"\"prev\":";
1957 (
const struct voistatdata *)&CONSTVSD(voistate, vsd)->prev,
1958 voi_dtype, voi_dtype, vsd_sz, fmt,
buf, objdump);
1960 case VSD_DTYPE_INT_S32:
1963 case VSD_DTYPE_INT_U32:
1966 case VSD_DTYPE_INT_S64:
1969 case VSD_DTYPE_INT_U64:
1972 case VSD_DTYPE_INT_SLONG:
1975 case VSD_DTYPE_INT_ULONG:
1978 case VSD_DTYPE_Q_S32:
1980 char qstr[Q_MAXSTRLEN(vsd->q32.sq32, 10)];
1981 Q_TOSTR((s32q_t)vsd->q32.sq32, -1, 10, qstr,
sizeof(qstr));
1985 case VSD_DTYPE_Q_U32:
1987 char qstr[Q_MAXSTRLEN(vsd->q32.uq32, 10)];
1988 Q_TOSTR((u32q_t)vsd->q32.uq32, -1, 10, qstr,
sizeof(qstr));
1992 case VSD_DTYPE_Q_S64:
1994 char qstr[Q_MAXSTRLEN(vsd->q64.sq64, 10)];
1995 Q_TOSTR((s64q_t)vsd->q64.sq64, -1, 10, qstr,
sizeof(qstr));
1999 case VSD_DTYPE_Q_U64:
2001 char qstr[Q_MAXSTRLEN(vsd->q64.uq64, 10)];
2002 Q_TOSTR((u64q_t)vsd->q64.uq64, -1, 10, qstr,
sizeof(qstr));
2006 case VSD_DTYPE_CRHIST32:
2007 case VSD_DTYPE_DRHIST32:
2008 case VSD_DTYPE_DVHIST32:
2009 case VSD_DTYPE_CRHIST64:
2010 case VSD_DTYPE_DRHIST64:
2011 case VSD_DTYPE_DVHIST64:
2013 vsd_dtype, vsd_sz, fmt,
buf, objdump);
2015 case VSD_DTYPE_TDGSTCLUST32:
2016 case VSD_DTYPE_TDGSTCLUST64:
2018 CONSTVSD(tdgst, vsd), vsd_dtype, vsd_sz, fmt,
buf,
2033 struct metablob *tpl_mb;
2040 tpl_mb = sctx->
tpl ? sctx->
tpl->mb : NULL;
2041 dump = ((sctx->
flags & SB_TOSTR_OBJDUMP) != 0);
2043 if (ctx->
flags & SB_IT_FIRST_CB) {
2047 "cursz=%hu, created=%jd, lastrst=%jd, flags=0x%04hx, "
2048 "stats_off=%hu, statsdata_off=%hu",
2056 if (ctx->
flags & SB_IT_FIRST_VOISTAT) {
2061 tpl_mb->voi_meta[v->
id].name);
2064 "voistatmaxid=%hhd, stats_off=%hu", v->
flags,
2068 if (!dump && vs->
stype <= 0)
2072 if (vs->
stype < 0) {
2094 struct metablob *tpl_mb;
2102 tpl_mb = sctx->
tpl ? sctx->
tpl->mb : NULL;
2103 dump = ((sctx->
flags & SB_TOSTR_OBJDUMP) != 0);
2105 if (ctx->
flags & SB_IT_FIRST_CB) {
2109 "\"maxsz\":%hu,\"cursz\":%hu,\"created\":%jd,"
2110 "\"lastrst\":%jd,\"flags\":%hu,\"stats_off\":%hu,"
2111 "\"statsdata_off\":%hu,", sb->
abi,
2118 fmtstr =
"\"tplname\":%s,\"tplhash\":%u,\"vois\":{";
2120 fmtstr =
"\"tplname\":\"%s\",\"tplhash\":%u,\"vois\":{";
2126 if (ctx->
flags & SB_IT_FIRST_VOISTAT) {
2136 fmtstr =
",\"name\":%s,\"flags\":%hu,"
2137 "\"dtype\":\"%s\",\"voistatmaxid\":%hhd,"
2138 "\"stats_off\":%hu,";
2140 fmtstr =
",\"name\":\"%s\",\"flags\":%hu,"
2141 "\"dtype\":\"%s\",\"voistatmaxid\":%hhd,"
2142 "\"stats_off\":%hu,";
2145 tpl_mb->voi_meta[v->
id].name :
"null", v->
flags,
2149 if (tpl_mb == NULL) {
2153 tpl_mb->voi_meta[v->
id].name);
2162 if (vs->
stype < 0) {
2167 "\"dtype\":\"%s\",\"data_off\":%hu,\"voistatdata\":{",
2170 }
else if (vs->
stype > 0) {
2190 if (ctx->
flags & SB_IT_LAST_VOISTAT)
2193 if (ctx->
flags & SB_IT_LAST_CB)
2207 switch (sctx->
fmt) {
2208 case SB_STRFMT_FREEFORM:
2211 case SB_STRFMT_JSON:
2223 enum sb_str_fmt
fmt, uint32_t
flags)
2228 if (sb == NULL || sb->
abi != STATS_ABI_V1 ||
buf == NULL ||
2229 fmt >= SB_STRFMT_NUM_FMTS)
2236 if (
flags & SB_TOSTR_META) {
2244 if (
flags & SB_TOSTR_OBJDUMP)
2245 iflags |= (SB_IT_NULLVOI | SB_IT_NULLVOISTAT);
2256 struct sb_visit sbv;
2262 sbv.voi_dtype = v->
dtype;
2263 sbv.vs_stype = vs->
stype;
2264 sbv.vs_dtype = vs->
dtype;
2265 sbv.vs_dsz = vs->
dsz;
2267 sbv.vs_errs = vs->
errs;
2268 sbv.flags = ctx->
flags & (SB_IT_FIRST_CB | SB_IT_LAST_CB |
2269 SB_IT_FIRST_VOI | SB_IT_LAST_VOI | SB_IT_FIRST_VOISTAT |
2270 SB_IT_LAST_VOISTAT);
2272 return (vctx->
cb(&sbv, vctx->
usrctx));
2281 if (sb == NULL || sb->
abi != STATS_ABI_V1 || func == NULL)
2298 if (vs->
stype == VS_STYPE_VOISTATE)
2304 switch (vs->
stype) {
2306 switch (vs->
dtype) {
2307 case VSD_DTYPE_Q_S32:
2308 Q_SIFVAL(VSD(q32, vsd)->sq32, 0);
2310 case VSD_DTYPE_Q_U32:
2311 Q_SIFVAL(VSD(q32, vsd)->uq32, 0);
2313 case VSD_DTYPE_Q_S64:
2314 Q_SIFVAL(VSD(q64, vsd)->sq64, 0);
2316 case VSD_DTYPE_Q_U64:
2317 Q_SIFVAL(VSD(q64, vsd)->uq64, 0);
2320 bzero(vsd, vs->
dsz);
2325 switch (vs->
dtype) {
2326 case VSD_DTYPE_Q_S32:
2327 Q_SIFVAL(VSD(q32, vsd)->sq32,
2328 Q_IFMINVAL(VSD(q32, vsd)->sq32));
2330 case VSD_DTYPE_Q_U32:
2331 Q_SIFVAL(VSD(q32, vsd)->uq32,
2332 Q_IFMINVAL(VSD(q32, vsd)->uq32));
2334 case VSD_DTYPE_Q_S64:
2335 Q_SIFVAL(VSD(q64, vsd)->sq64,
2336 Q_IFMINVAL(VSD(q64, vsd)->sq64));
2338 case VSD_DTYPE_Q_U64:
2339 Q_SIFVAL(VSD(q64, vsd)->uq64,
2340 Q_IFMINVAL(VSD(q64, vsd)->uq64));
2349 switch (vs->
dtype) {
2350 case VSD_DTYPE_Q_S32:
2351 Q_SIFVAL(VSD(q32, vsd)->sq32,
2352 Q_IFMAXVAL(VSD(q32, vsd)->sq32));
2354 case VSD_DTYPE_Q_U32:
2355 Q_SIFVAL(VSD(q32, vsd)->uq32,
2356 Q_IFMAXVAL(VSD(q32, vsd)->uq32));
2358 case VSD_DTYPE_Q_S64:
2359 Q_SIFVAL(VSD(q64, vsd)->sq64,
2360 Q_IFMAXVAL(VSD(q64, vsd)->sq64));
2362 case VSD_DTYPE_Q_U64:
2363 Q_SIFVAL(VSD(q64, vsd)->uq64,
2364 Q_IFMAXVAL(VSD(q64, vsd)->uq64));
2375 struct voistatdata_hist *hist;
2379 hist = VSD(hist, vsd);
2380 switch (vs->
dtype) {
2381 case VSD_DTYPE_CRHIST32:
2382 nbkts = HIST_VSDSZ2NBKTS(crhist32, vs->
dsz);
2385 case VSD_DTYPE_DRHIST32:
2386 nbkts = HIST_VSDSZ2NBKTS(drhist32, vs->
dsz);
2389 case VSD_DTYPE_DVHIST32:
2390 nbkts = HIST_VSDSZ2NBKTS(dvhist32, vs->
dsz);
2393 case VSD_DTYPE_CRHIST64:
2394 nbkts = HIST_VSDSZ2NBKTS(crhist64, vs->
dsz);
2397 case VSD_DTYPE_DRHIST64:
2398 nbkts = HIST_VSDSZ2NBKTS(drhist64, vs->
dsz);
2401 case VSD_DTYPE_DVHIST64:
2402 nbkts = HIST_VSDSZ2NBKTS(dvhist64, vs->
dsz);
2409 bzero(VSD_HIST_FIELDPTR(hist, vs->
dtype, oob),
2410 is32bit ?
sizeof(uint32_t) :
sizeof(uint64_t));
2411 for (i = nbkts - 1; i >= 0; i--) {
2412 bzero(VSD_HIST_FIELDPTR(hist, vs->
dtype,
2413 bkts[i].cnt), is32bit ?
sizeof(uint32_t) :
2418 case VS_STYPE_TDGST:
2421 struct voistatdata_tdgst *tdgst;
2422 struct ctdth32 *ctd32tree;
2423 struct ctdth64 *ctd64tree;
2424 struct voistatdata_tdgstctd32 *ctd32;
2425 struct voistatdata_tdgstctd64 *ctd64;
2427 tdgst = VSD(tdgst, vsd);
2428 switch (vs->
dtype) {
2429 case VSD_DTYPE_TDGSTCLUST32:
2430 VSD(tdgstclust32, tdgst)->smplcnt = 0;
2431 VSD(tdgstclust32, tdgst)->compcnt = 0;
2432 ctd32tree = &VSD(tdgstclust32, tdgst)->ctdtree;
2433 ARB_INIT(ctd32, ctdlnk, ctd32tree,
2434 ARB_MAXNODES(ctd32tree)) {
2436 Q_SIFVAL(ctd32->mu, 0);
2439 RB_INIT(&VSD(tdgstclust32, tdgst)->rbctdtree);
2442 case VSD_DTYPE_TDGSTCLUST64:
2443 VSD(tdgstclust64, tdgst)->smplcnt = 0;
2444 VSD(tdgstclust64, tdgst)->compcnt = 0;
2445 ctd64tree = &VSD(tdgstclust64, tdgst)->ctdtree;
2446 ARB_INIT(ctd64, ctdlnk, ctd64tree,
2447 ARB_MAXNODES(ctd64tree)) {
2449 Q_SIFVAL(ctd64->mu, 0);
2452 RB_INIT(&VSD(tdgstclust64, tdgst)->rbctdtree);
2461 KASSERT(0, (
"Unknown VOI stat type %d", vs->
stype));
2466 vs->
flags &= ~VS_VSDVALID;
2477 if (
src != NULL &&
src->abi == STATS_ABI_V1) {
2480 if (
flags & SB_CLONE_RSTSRC) {
2495 struct voistatdata *voival,
struct voistat *vs,
void *vsd)
2499 KASSERT(vs->
dtype < VSD_NUM_DTYPES,
2500 (
"Unknown VSD dtype %d", vs->
dtype));
2504 switch (vs->
dtype) {
2505 case VSD_DTYPE_INT_S32:
2506 if (VSD(int32, vsd)->s32 < voival->int32.s32) {
2507 VSD(int32, vsd)->s32 = voival->int32.s32;
2511 case VSD_DTYPE_INT_U32:
2512 if (VSD(int32, vsd)->u32 < voival->int32.u32) {
2513 VSD(int32, vsd)->u32 = voival->int32.u32;
2517 case VSD_DTYPE_INT_S64:
2518 if (VSD(int64, vsd)->s64 < voival->int64.s64) {
2519 VSD(int64, vsd)->s64 = voival->int64.s64;
2523 case VSD_DTYPE_INT_U64:
2524 if (VSD(int64, vsd)->u64 < voival->int64.u64) {
2525 VSD(int64, vsd)->u64 = voival->int64.u64;
2529 case VSD_DTYPE_INT_SLONG:
2530 if (VSD(intlong, vsd)->slong < voival->intlong.slong) {
2531 VSD(intlong, vsd)->slong = voival->intlong.slong;
2535 case VSD_DTYPE_INT_ULONG:
2536 if (VSD(intlong, vsd)->ulong < voival->intlong.ulong) {
2537 VSD(intlong, vsd)->ulong = voival->intlong.ulong;
2541 case VSD_DTYPE_Q_S32:
2542 if (Q_QLTQ(VSD(q32, vsd)->sq32, voival->q32.sq32) &&
2543 (0 == (error = Q_QCPYVALQ(&VSD(q32, vsd)->sq32,
2544 voival->q32.sq32)))) {
2548 case VSD_DTYPE_Q_U32:
2549 if (Q_QLTQ(VSD(q32, vsd)->uq32, voival->q32.uq32) &&
2550 (0 == (error = Q_QCPYVALQ(&VSD(q32, vsd)->uq32,
2551 voival->q32.uq32)))) {
2555 case VSD_DTYPE_Q_S64:
2556 if (Q_QLTQ(VSD(q64, vsd)->sq64, voival->q64.sq64) &&
2557 (0 == (error = Q_QCPYVALQ(&VSD(q64, vsd)->sq64,
2558 voival->q64.sq64)))) {
2562 case VSD_DTYPE_Q_U64:
2563 if (Q_QLTQ(VSD(q64, vsd)->uq64, voival->q64.uq64) &&
2564 (0 == (error = Q_QCPYVALQ(&VSD(q64, vsd)->uq64,
2565 voival->q64.uq64)))) {
2579 struct voistatdata *voival,
struct voistat *vs,
void *vsd)
2583 KASSERT(vs->
dtype < VSD_NUM_DTYPES,
2584 (
"Unknown VSD dtype %d", vs->
dtype));
2588 switch (vs->
dtype) {
2589 case VSD_DTYPE_INT_S32:
2590 if (VSD(int32, vsd)->s32 > voival->int32.s32) {
2591 VSD(int32, vsd)->s32 = voival->int32.s32;
2595 case VSD_DTYPE_INT_U32:
2596 if (VSD(int32, vsd)->u32 > voival->int32.u32) {
2597 VSD(int32, vsd)->u32 = voival->int32.u32;
2601 case VSD_DTYPE_INT_S64:
2602 if (VSD(int64, vsd)->s64 > voival->int64.s64) {
2603 VSD(int64, vsd)->s64 = voival->int64.s64;
2607 case VSD_DTYPE_INT_U64:
2608 if (VSD(int64, vsd)->u64 > voival->int64.u64) {
2609 VSD(int64, vsd)->u64 = voival->int64.u64;
2613 case VSD_DTYPE_INT_SLONG:
2614 if (VSD(intlong, vsd)->slong > voival->intlong.slong) {
2615 VSD(intlong, vsd)->slong = voival->intlong.slong;
2619 case VSD_DTYPE_INT_ULONG:
2620 if (VSD(intlong, vsd)->ulong > voival->intlong.ulong) {
2621 VSD(intlong, vsd)->ulong = voival->intlong.ulong;
2625 case VSD_DTYPE_Q_S32:
2626 if (Q_QGTQ(VSD(q32, vsd)->sq32, voival->q32.sq32) &&
2627 (0 == (error = Q_QCPYVALQ(&VSD(q32, vsd)->sq32,
2628 voival->q32.sq32)))) {
2632 case VSD_DTYPE_Q_U32:
2633 if (Q_QGTQ(VSD(q32, vsd)->uq32, voival->q32.uq32) &&
2634 (0 == (error = Q_QCPYVALQ(&VSD(q32, vsd)->uq32,
2635 voival->q32.uq32)))) {
2639 case VSD_DTYPE_Q_S64:
2640 if (Q_QGTQ(VSD(q64, vsd)->sq64, voival->q64.sq64) &&
2641 (0 == (error = Q_QCPYVALQ(&VSD(q64, vsd)->sq64,
2642 voival->q64.sq64)))) {
2646 case VSD_DTYPE_Q_U64:
2647 if (Q_QGTQ(VSD(q64, vsd)->uq64, voival->q64.uq64) &&
2648 (0 == (error = Q_QCPYVALQ(&VSD(q64, vsd)->uq64,
2649 voival->q64.uq64)))) {
2663 struct voistatdata *voival,
struct voistat *vs,
void *vsd)
2667 KASSERT(vs->
dtype < VSD_NUM_DTYPES,
2668 (
"Unknown VSD dtype %d", vs->
dtype));
2672 switch (vs->
dtype) {
2673 case VSD_DTYPE_INT_S32:
2674 VSD(int32, vsd)->s32 += voival->int32.s32;
2676 case VSD_DTYPE_INT_U32:
2677 VSD(int32, vsd)->u32 += voival->int32.u32;
2679 case VSD_DTYPE_INT_S64:
2680 VSD(int64, vsd)->s64 += voival->int64.s64;
2682 case VSD_DTYPE_INT_U64:
2683 VSD(int64, vsd)->u64 += voival->int64.u64;
2685 case VSD_DTYPE_INT_SLONG:
2686 VSD(intlong, vsd)->slong += voival->intlong.slong;
2688 case VSD_DTYPE_INT_ULONG:
2689 VSD(intlong, vsd)->ulong += voival->intlong.ulong;
2691 case VSD_DTYPE_Q_S32:
2692 error = Q_QADDQ(&VSD(q32, vsd)->sq32, voival->q32.sq32);
2694 case VSD_DTYPE_Q_U32:
2695 error = Q_QADDQ(&VSD(q32, vsd)->uq32, voival->q32.uq32);
2697 case VSD_DTYPE_Q_S64:
2698 error = Q_QADDQ(&VSD(q64, vsd)->sq64, voival->q64.sq64);
2700 case VSD_DTYPE_Q_U64:
2701 error = Q_QADDQ(&VSD(q64, vsd)->uq64, voival->q64.uq64);
2716 struct voistat *vs,
struct voistatdata_hist *hist)
2718 struct voistatdata_numeric *bkt_lb, *bkt_ub;
2719 uint64_t *oob64, *cnt64;
2720 uint32_t *oob32, *cnt32;
2721 int error, i, found, is32bit, has_ub, eq_only;
2725 switch (vs->
dtype) {
2726 case VSD_DTYPE_CRHIST32:
2727 i = HIST_VSDSZ2NBKTS(crhist32, vs->
dsz);
2729 has_ub = eq_only = 0;
2730 oob32 = &VSD(crhist32, hist)->oob;
2732 case VSD_DTYPE_DRHIST32:
2733 i = HIST_VSDSZ2NBKTS(drhist32, vs->
dsz);
2734 is32bit = has_ub = 1;
2736 oob32 = &VSD(drhist32, hist)->oob;
2738 case VSD_DTYPE_DVHIST32:
2739 i = HIST_VSDSZ2NBKTS(dvhist32, vs->
dsz);
2740 is32bit = eq_only = 1;
2742 oob32 = &VSD(dvhist32, hist)->oob;
2744 case VSD_DTYPE_CRHIST64:
2745 i = HIST_VSDSZ2NBKTS(crhist64, vs->
dsz);
2746 is32bit = has_ub = eq_only = 0;
2747 oob64 = &VSD(crhist64, hist)->oob;
2749 case VSD_DTYPE_DRHIST64:
2750 i = HIST_VSDSZ2NBKTS(drhist64, vs->
dsz);
2751 is32bit = eq_only = 0;
2753 oob64 = &VSD(drhist64, hist)->oob;
2755 case VSD_DTYPE_DVHIST64:
2756 i = HIST_VSDSZ2NBKTS(dvhist64, vs->
dsz);
2757 is32bit = has_ub = 0;
2759 oob64 = &VSD(dvhist64, hist)->oob;
2767 for (found = 0; i >= 0 && !found; i--) {
2768 switch (vs->
dtype) {
2769 case VSD_DTYPE_CRHIST32:
2770 bkt_lb = &VSD(crhist32, hist)->bkts[i].lb;
2771 cnt32 = &VSD(crhist32, hist)->bkts[i].cnt;
2773 case VSD_DTYPE_DRHIST32:
2774 bkt_lb = &VSD(drhist32, hist)->bkts[i].lb;
2775 bkt_ub = &VSD(drhist32, hist)->bkts[i].ub;
2776 cnt32 = &VSD(drhist32, hist)->bkts[i].cnt;
2778 case VSD_DTYPE_DVHIST32:
2779 bkt_lb = &VSD(dvhist32, hist)->bkts[i].val;
2780 cnt32 = &VSD(dvhist32, hist)->bkts[i].cnt;
2782 case VSD_DTYPE_CRHIST64:
2783 bkt_lb = &VSD(crhist64, hist)->bkts[i].lb;
2784 cnt64 = &VSD(crhist64, hist)->bkts[i].cnt;
2786 case VSD_DTYPE_DRHIST64:
2787 bkt_lb = &VSD(drhist64, hist)->bkts[i].lb;
2788 bkt_ub = &VSD(drhist64, hist)->bkts[i].ub;
2789 cnt64 = &VSD(drhist64, hist)->bkts[i].cnt;
2791 case VSD_DTYPE_DVHIST64:
2792 bkt_lb = &VSD(dvhist64, hist)->bkts[i].val;
2793 cnt64 = &VSD(dvhist64, hist)->bkts[i].cnt;
2799 switch (voi_dtype) {
2800 case VSD_DTYPE_INT_S32:
2801 if (voival->int32.s32 >= bkt_lb->int32.s32) {
2802 if ((eq_only && voival->int32.s32 ==
2803 bkt_lb->int32.s32) ||
2804 (!eq_only && (!has_ub ||
2805 voival->int32.s32 < bkt_ub->int32.s32)))
2809 case VSD_DTYPE_INT_U32:
2810 if (voival->int32.u32 >= bkt_lb->int32.u32) {
2811 if ((eq_only && voival->int32.u32 ==
2812 bkt_lb->int32.u32) ||
2813 (!eq_only && (!has_ub ||
2814 voival->int32.u32 < bkt_ub->int32.u32)))
2818 case VSD_DTYPE_INT_S64:
2819 if (voival->int64.s64 >= bkt_lb->int64.s64)
2820 if ((eq_only && voival->int64.s64 ==
2821 bkt_lb->int64.s64) ||
2822 (!eq_only && (!has_ub ||
2823 voival->int64.s64 < bkt_ub->int64.s64)))
2826 case VSD_DTYPE_INT_U64:
2827 if (voival->int64.u64 >= bkt_lb->int64.u64)
2828 if ((eq_only && voival->int64.u64 ==
2829 bkt_lb->int64.u64) ||
2830 (!eq_only && (!has_ub ||
2831 voival->int64.u64 < bkt_ub->int64.u64)))
2834 case VSD_DTYPE_INT_SLONG:
2835 if (voival->intlong.slong >= bkt_lb->intlong.slong)
2836 if ((eq_only && voival->intlong.slong ==
2837 bkt_lb->intlong.slong) ||
2838 (!eq_only && (!has_ub ||
2839 voival->intlong.slong <
2840 bkt_ub->intlong.slong)))
2843 case VSD_DTYPE_INT_ULONG:
2844 if (voival->intlong.ulong >= bkt_lb->intlong.ulong)
2845 if ((eq_only && voival->intlong.ulong ==
2846 bkt_lb->intlong.ulong) ||
2847 (!eq_only && (!has_ub ||
2848 voival->intlong.ulong <
2849 bkt_ub->intlong.ulong)))
2852 case VSD_DTYPE_Q_S32:
2853 if (Q_QGEQ(voival->q32.sq32, bkt_lb->q32.sq32))
2854 if ((eq_only && Q_QEQ(voival->q32.sq32,
2855 bkt_lb->q32.sq32)) ||
2856 (!eq_only && (!has_ub ||
2857 Q_QLTQ(voival->q32.sq32,
2858 bkt_ub->q32.sq32))))
2861 case VSD_DTYPE_Q_U32:
2862 if (Q_QGEQ(voival->q32.uq32, bkt_lb->q32.uq32))
2863 if ((eq_only && Q_QEQ(voival->q32.uq32,
2864 bkt_lb->q32.uq32)) ||
2865 (!eq_only && (!has_ub ||
2866 Q_QLTQ(voival->q32.uq32,
2867 bkt_ub->q32.uq32))))
2870 case VSD_DTYPE_Q_S64:
2871 if (Q_QGEQ(voival->q64.sq64, bkt_lb->q64.sq64))
2872 if ((eq_only && Q_QEQ(voival->q64.sq64,
2873 bkt_lb->q64.sq64)) ||
2874 (!eq_only && (!has_ub ||
2875 Q_QLTQ(voival->q64.sq64,
2876 bkt_ub->q64.sq64))))
2879 case VSD_DTYPE_Q_U64:
2880 if (Q_QGEQ(voival->q64.uq64, bkt_lb->q64.uq64))
2881 if ((eq_only && Q_QEQ(voival->q64.uq64,
2882 bkt_lb->q64.uq64)) ||
2883 (!eq_only && (!has_ub ||
2884 Q_QLTQ(voival->q64.uq64,
2885 bkt_ub->q64.uq64))))
2911 struct voistatdata_tdgst *tdgst,
int attempt)
2913 struct ctdth32 *ctd32tree;
2914 struct ctdth64 *ctd64tree;
2915 struct voistatdata_tdgstctd32 *ctd32;
2916 struct voistatdata_tdgstctd64 *ctd64;
2917 uint64_t ebits, idxmask;
2918 uint32_t bitsperidx, nebits;
2919 int error, idx, is32bit, maxctds, remctds, tmperr;
2924 case VSD_DTYPE_TDGSTCLUST32:
2925 ctd32tree = &VSD(tdgstclust32, tdgst)->ctdtree;
2926 if (!ARB_FULL(ctd32tree))
2928 VSD(tdgstclust32, tdgst)->compcnt++;
2929 maxctds = remctds = ARB_MAXNODES(ctd32tree);
2930 ARB_RESET_TREE(ctd32tree, ctdth32, maxctds);
2931 VSD(tdgstclust32, tdgst)->smplcnt = 0;
2936 RB_INIT(&VSD(tdgstclust32, tdgst)->rbctdtree);
2939 case VSD_DTYPE_TDGSTCLUST64:
2940 ctd64tree = &VSD(tdgstclust64, tdgst)->ctdtree;
2941 if (!ARB_FULL(ctd64tree))
2943 VSD(tdgstclust64, tdgst)->compcnt++;
2944 maxctds = remctds = ARB_MAXNODES(ctd64tree);
2945 ARB_RESET_TREE(ctd64tree, ctdth64, maxctds);
2946 VSD(tdgstclust64, tdgst)->smplcnt = 0;
2951 RB_INIT(&VSD(tdgstclust64, tdgst)->rbctdtree);
2970#define bitsperrand 31
2973 bitsperidx = fls(maxctds);
2974 KASSERT(bitsperidx <=
sizeof(ebits) << 3,
2975 (
"%s: bitsperidx=%d, ebits=%d",
2976 __func__, bitsperidx, (
int)(
sizeof(ebits) << 3)));
2977 idxmask = (UINT64_C(1) << bitsperidx) - 1;
2980 for (; remctds > 0; remctds--) {
2981 while (nebits < bitsperidx) {
2982 ebits |= ((uint64_t)random()) << nebits;
2984 if (nebits > (
sizeof(ebits) << 3))
2985 nebits =
sizeof(ebits) << 3;
2987 idx = ebits & idxmask;
2988 nebits -= bitsperidx;
2989 ebits >>= bitsperidx;
3002 ctd32 = ARB_NODE(ctd32tree, idx);
3004 ctd64 = ARB_NODE(ctd64tree, idx);
3005 }
while ((is32bit ? ARB_ISFREE(ctd32, ctdlnk) :
3006 ARB_ISFREE(ctd64, ctdlnk)) && ++idx);
3010 ARB_RETURNFREE(ctd32tree, ctd32, ctdlnk);
3012 ARB_RETURNFREE(ctd64tree, ctd64, ctdlnk);
3025 ARB_FREEIDX(ctd32tree) == ARB_SELFIDX(ctd32tree, ctd32) :
3026 ARB_FREEIDX(ctd64tree) == ARB_SELFIDX(ctd64tree, ctd64)),
3027 (
"%s: t-digest ARB@%p free list bug", __func__,
3028 (is32bit ? (
void *)ctd32tree : (
void *)ctd64tree)));
3030 while ((is32bit ? ctd32 != NULL : ctd64 != NULL)) {
3035 idx = ARB_NEXTFREEIDX(ctd32, ctdlnk);
3037 tmperr = Q_QCLONEQ(&x, ctd32->mu);
3039 vs_dtype, tdgst, x, ctd32->cnt, attempt);
3040 ctd32 = ARB_NODE(ctd32tree, idx);
3041 KASSERT(ctd32 == NULL || ARB_ISFREE(ctd32, ctdlnk),
3042 (
"%s: t-digest ARB@%p free list bug", __func__,
3045 idx = ARB_NEXTFREEIDX(ctd64, ctdlnk);
3047 ctd64->mu, ctd64->cnt, attempt);
3048 ctd64 = ARB_NODE(ctd64tree, idx);
3049 KASSERT(ctd64 == NULL || ARB_ISFREE(ctd64, ctdlnk),
3050 (
"%s: t-digest ARB@%p free list bug", __func__,
3057 error = tmperr ? tmperr : error;
3061 KASSERT(remctds == 0, (
"%s: t-digest ARB@%p free list bug", __func__,
3062 (is32bit ? (
void *)ctd32tree : (
void *)ctd64tree)));
3069 s64q_t x, uint64_t weight,
int attempt)
3072 char qstr[Q_MAXSTRLEN(x, 10)];
3074 struct ctdth32 *ctd32tree;
3075 struct ctdth64 *ctd64tree;
3076 void *closest, *cur, *lb, *ub;
3077 struct voistatdata_tdgstctd32 *ctd32;
3078 struct voistatdata_tdgstctd64 *ctd64;
3079 uint64_t cnt, smplcnt, sum, tmpsum;
3080 s64q_t k, minz, q, z;
3081 int error, is32bit, n;
3084 minz = Q_INI(&z, 0, 0, Q_NFBITS(x));
3087 case VSD_DTYPE_TDGSTCLUST32:
3088 if ((UINT32_MAX - weight) < VSD(tdgstclust32, tdgst)->smplcnt)
3090 smplcnt = VSD(tdgstclust32, tdgst)->smplcnt;
3091 ctd32tree = &VSD(tdgstclust32, tdgst)->ctdtree;
3096 case VSD_DTYPE_TDGSTCLUST64:
3097 if ((UINT64_MAX - weight) < VSD(tdgstclust64, tdgst)->smplcnt)
3099 smplcnt = VSD(tdgstclust64, tdgst)->smplcnt;
3100 ctd64tree = &VSD(tdgstclust64, tdgst)->ctdtree;
3117#if defined(DIAGNOSTIC)
3118 KASSERT(attempt < 5,
3119 (
"%s: Too many attempts", __func__));
3124 Q_SIFVAL(minz, Q_IFMAXVAL(minz));
3125 closest = ub = NULL;
3129 lb = cur = (
void *)(ctd32 = ARB_MIN(ctdth32, ctd32tree));
3131 lb = cur = (
void *)(ctd64 = ARB_MIN(ctdth64, ctd64tree));
3134 lb = (is32bit ? (
void *)ARB_ROOT(ctd32tree) :
3135 (
void *)ARB_ROOT(ctd64tree));
3144 (
void *)(ctd32 = ARB_NEXT(ctdth32, ctd32tree, ctd32)) :
3145 (
void *)(ctd64 = ARB_NEXT(ctdth64, ctd64tree, ctd64)))) {
3148 KASSERT(Q_PRECEQ(ctd32->mu, x),
3149 (
"%s: Q_RELPREC(mu,x)=%d", __func__,
3150 Q_RELPREC(ctd32->mu, x)));
3155 KASSERT(Q_PRECEQ(ctd64->mu, x),
3156 (
"%s: Q_RELPREC(mu,x)=%d", __func__,
3157 Q_RELPREC(ctd64->mu, x)));
3162 error = Q_QSUBQ(&z, x);
3163#if defined(DIAGNOSTIC)
3164 KASSERT(!error, (
"%s: unexpected error %d", __func__,
3171 if (Q_QLTQ(z, minz)) {
3176 }
else if (Q_QGTQ(z, minz)) {
3183 (
void *)(ctd32 = (
struct voistatdata_tdgstctd32 *)lb) :
3184 (
void *)(ctd64 = (
struct voistatdata_tdgstctd64 *)lb));
3186 for (n = 0; cur != ub; cur = (is32bit ?
3187 (
void *)(ctd32 = ARB_NEXT(ctdth32, ctd32tree, ctd32)) :
3188 (
void *)(ctd64 = ARB_NEXT(ctdth64, ctd64tree, ctd64)))) {
3196 error = Q_QFRACI(&q, 1, 2);
3199 error = Q_QFRACI(&q, (sum << 1) + cnt - 1,
3200 (smplcnt - 1) << 1);
3203 error |= Q_QMULI(&k, 4 * smplcnt * attempt);
3205 error |= Q_QSUBI(&q, 1);
3207 error |= Q_QMULQ(&k, q);
3208#if defined(DIAGNOSTIC)
3209#if !defined(_KERNEL)
3210 double q_dbl, k_dbl, q2d, k2d;
3213 q_dbl = smplcnt == 1 ? 0.5 :
3214 (sum + ((cnt - 1) / 2.0)) / (
double)(smplcnt - 1);
3215 k_dbl = 4 * smplcnt * q_dbl * (1.0 - q_dbl) * attempt;
3221 q_dbl = 1.0 - q_dbl;
3222 KASSERT((q_dbl > q2d ? q_dbl - q2d : q2d - q_dbl) <
3223 (1.05 * ((
double)1 / (
double)(1ULL << Q_NFBITS(q)))),
3224 (
"Q-type q bad precision"));
3225 KASSERT((k_dbl > k2d ? k_dbl - k2d : k2d - k_dbl) <
3226 1.0 + (0.01 * smplcnt),
3227 (
"Q-type k bad precision"));
3229 KASSERT(!error, (
"%s: unexpected error %d", __func__,
3234 if ((is32bit && ((ctd32->cnt + weight) <=
3235 (uint64_t)Q_GIVAL(k))) ||
3236 (!is32bit && ((ctd64->cnt + weight) <=
3237 (uint64_t)Q_GIVAL(k)))) {
3240 if (random() < (INT32_MAX / n))
3245 }
while (closest == NULL &&
3246 (is32bit ? ARB_FULL(ctd32tree) : ARB_FULL(ctd64tree)) &&
3253 if (closest != NULL) {
3256 ctd32 = (
struct voistatdata_tdgstctd32 *)closest;
3257 error = Q_QSUBQ(&x, ctd32->mu);
3289 error = error ? error :
3290 Q_QDIVI(&x, ctd32->cnt + weight);
3291 if ((error && error != ERANGE)
3292 || (error = Q_QADDQ(&ctd32->mu, x))) {
3294 KASSERT(!error, (
"%s: unexpected error %d",
3299 ctd32->cnt += weight;
3300 error = ARB_REINSERT(ctdth32, ctd32tree, ctd32) ==
3301 NULL ? 0 : EALREADY;
3303 RB_REINSERT(rbctdth32,
3304 &VSD(tdgstclust32, tdgst)->rbctdtree, ctd32);
3307 ctd64 = (
struct voistatdata_tdgstctd64 *)closest;
3308 error = Q_QSUBQ(&x, ctd64->mu);
3309 error = error ? error :
3310 Q_QDIVI(&x, ctd64->cnt + weight);
3312 if ((error && error != ERANGE)
3313 || (error = Q_QADDQ(&ctd64->mu, x))) {
3314 KASSERT(!error, (
"%s: unexpected error %d",
3318 ctd64->cnt += weight;
3319 error = ARB_REINSERT(ctdth64, ctd64tree, ctd64) ==
3320 NULL ? 0 : EALREADY;
3322 RB_REINSERT(rbctdth64,
3323 &VSD(tdgstclust64, tdgst)->rbctdtree, ctd64);
3332 ctd32 = ARB_GETFREE(ctd32tree, ctdlnk);
3334 KASSERT(ctd32 != NULL,
3335 (
"%s: t-digest@%p has no free centroids",
3340 if ((error = Q_QCPYVALQ(&ctd32->mu, x)))
3342 ctd32->cnt = weight;
3343 error = ARB_INSERT(ctdth32, ctd32tree, ctd32) == NULL ?
3346 RB_INSERT(rbctdth32,
3347 &VSD(tdgstclust32, tdgst)->rbctdtree, ctd32);
3350 ctd64 = ARB_GETFREE(ctd64tree, ctdlnk);
3352 KASSERT(ctd64 != NULL,
3353 (
"%s: t-digest@%p has no free centroids",
3360 ctd64->cnt = weight;
3361 error = ARB_INSERT(ctdth64, ctd64tree, ctd64) == NULL ?
3364 RB_INSERT(rbctdth64, &VSD(tdgstclust64,
3365 tdgst)->rbctdtree, ctd64);
3371 VSD(tdgstclust32, tdgst)->smplcnt += weight;
3373 VSD(tdgstclust64, tdgst)->smplcnt += weight;
3376 struct rbctdth64 *rbctdtree =
3377 &VSD(tdgstclust64, tdgst)->rbctdtree;
3378 struct voistatdata_tdgstctd64 *rbctd64;
3380 ARB_FOREACH(ctd64, ctdth64, ctd64tree) {
3381 rbctd64 = (i == 0 ? RB_MIN(rbctdth64, rbctdtree) :
3382 RB_NEXT(rbctdth64, rbctdtree, rbctd64));
3384 if (i >= ARB_CURNODES(ctd64tree)
3386 || ARB_MIN(ctdth64, ctd64tree) !=
3387 RB_MIN(rbctdth64, rbctdtree)
3388 || ARB_MAX(ctdth64, ctd64tree) !=
3389 RB_MAX(rbctdth64, rbctdtree)
3390 || ARB_LEFTIDX(ctd64, ctdlnk) !=
3391 ARB_SELFIDX(ctd64tree, RB_LEFT(rbctd64, rblnk))
3392 || ARB_RIGHTIDX(ctd64, ctdlnk) !=
3393 ARB_SELFIDX(ctd64tree, RB_RIGHT(rbctd64, rblnk))
3394 || ARB_PARENTIDX(ctd64, ctdlnk) !=
3395 ARB_SELFIDX(ctd64tree,
3396 RB_PARENT(rbctd64, rblnk))) {
3397 Q_TOSTR(ctd64->mu, -1, 10, qstr,
sizeof(qstr));
3398 printf(
"ARB ctd=%3d p=%3d l=%3d r=%3d c=%2d "
3400 (
int)ARB_SELFIDX(ctd64tree, ctd64),
3401 ARB_PARENTIDX(ctd64, ctdlnk),
3402 ARB_LEFTIDX(ctd64, ctdlnk),
3403 ARB_RIGHTIDX(ctd64, ctdlnk),
3404 ARB_COLOR(ctd64, ctdlnk),
3407 Q_TOSTR(rbctd64->mu, -1, 10, qstr,
3409 printf(
" RB ctd=%3d p=%3d l=%3d r=%3d c=%2d "
3411 (
int)ARB_SELFIDX(ctd64tree, rbctd64),
3412 (
int)ARB_SELFIDX(ctd64tree,
3413 RB_PARENT(rbctd64, rblnk)),
3414 (
int)ARB_SELFIDX(ctd64tree,
3415 RB_LEFT(rbctd64, rblnk)),
3416 (
int)ARB_SELFIDX(ctd64tree,
3417 RB_RIGHT(rbctd64, rblnk)),
3418 RB_COLOR(rbctd64, rblnk),
3421 panic(
"RB@%p and ARB@%p trees differ\n",
3422 rbctdtree, ctd64tree);
3434 struct voistat *vs,
struct voistatdata_tdgst *tdgst)
3441 switch (vs->
dtype) {
3442 case VSD_DTYPE_TDGSTCLUST32:
3444 Q_INI(&x, 0, 0, Q_NFBITS(
3445 ARB_CNODE(&VSD(tdgstclust32, tdgst)->ctdtree, 0)->mu));
3447 case VSD_DTYPE_TDGSTCLUST64:
3449 Q_INI(&x, 0, 0, Q_NFBITS(
3450 ARB_CNODE(&VSD(tdgstclust64, tdgst)->ctdtree, 0)->mu));
3453 KASSERT(vs->
dtype == VSD_DTYPE_TDGSTCLUST32 ||
3454 vs->
dtype == VSD_DTYPE_TDGSTCLUST64,
3455 (
"%s: vs->dtype(%d) != VSD_DTYPE_TDGSTCLUST<32|64>",
3456 __func__, vs->
dtype));
3464 switch (voi_dtype) {
3465 case VSD_DTYPE_INT_S32:
3466 error = Q_QCPYVALI(&x, voival->int32.s32);
3468 case VSD_DTYPE_INT_U32:
3469 error = Q_QCPYVALI(&x, voival->int32.u32);
3471 case VSD_DTYPE_INT_S64:
3472 error = Q_QCPYVALI(&x, voival->int64.s64);
3474 case VSD_DTYPE_INT_U64:
3475 error = Q_QCPYVALI(&x, voival->int64.u64);
3477 case VSD_DTYPE_INT_SLONG:
3478 error = Q_QCPYVALI(&x, voival->intlong.slong);
3480 case VSD_DTYPE_INT_ULONG:
3481 error = Q_QCPYVALI(&x, voival->intlong.ulong);
3483 case VSD_DTYPE_Q_S32:
3484 error = Q_QCPYVALQ(&x, voival->q32.sq32);
3486 case VSD_DTYPE_Q_U32:
3487 error = Q_QCPYVALQ(&x, voival->q32.uq32);
3489 case VSD_DTYPE_Q_S64:
3490 error = Q_QCPYVALQ(&x, voival->q64.sq64);
3492 case VSD_DTYPE_Q_U64:
3493 error = Q_QCPYVALQ(&x, voival->q64.uq64);
3510 enum vsd_dtype voi_dtype,
struct voistatdata *voival, uint32_t
flags)
3514 void *statevsd, *vsd;
3515 int error, i, tmperr;
3519 if (sb == NULL || sb->
abi != STATS_ABI_V1 || voi_id >=
NVOIS(sb) ||
3520 voi_dtype == 0 || voi_dtype >= VSD_NUM_DTYPES || voival == NULL)
3522 v = &sb->
vois[voi_id];
3523 if (voi_dtype != v->
dtype || v->
id < 0 ||
3533 if (
flags & SB_VOI_RELUPDATE) {
3534 switch (voi_dtype) {
3535 case VSD_DTYPE_INT_S32:
3536 voival->int32.s32 +=
3537 VSD(voistate, statevsd)->
prev.int32.s32;
3539 case VSD_DTYPE_INT_U32:
3540 voival->int32.u32 +=
3541 VSD(voistate, statevsd)->prev.int32.u32;
3543 case VSD_DTYPE_INT_S64:
3544 voival->int64.s64 +=
3545 VSD(voistate, statevsd)->prev.int64.s64;
3547 case VSD_DTYPE_INT_U64:
3548 voival->int64.u64 +=
3549 VSD(voistate, statevsd)->prev.int64.u64;
3551 case VSD_DTYPE_INT_SLONG:
3552 voival->intlong.slong +=
3553 VSD(voistate, statevsd)->prev.intlong.slong;
3555 case VSD_DTYPE_INT_ULONG:
3556 voival->intlong.ulong +=
3557 VSD(voistate, statevsd)->prev.intlong.ulong;
3559 case VSD_DTYPE_Q_S32:
3560 error = Q_QADDQ(&voival->q32.sq32,
3561 VSD(voistate, statevsd)->prev.q32.sq32);
3563 case VSD_DTYPE_Q_U32:
3564 error = Q_QADDQ(&voival->q32.uq32,
3565 VSD(voistate, statevsd)->prev.q32.uq32);
3567 case VSD_DTYPE_Q_S64:
3568 error = Q_QADDQ(&voival->q64.sq64,
3569 VSD(voistate, statevsd)->prev.q64.sq64);
3571 case VSD_DTYPE_Q_U64:
3572 error = Q_QADDQ(&voival->q64.uq64,
3573 VSD(voistate, statevsd)->prev.q64.uq64);
3576 KASSERT(0, (
"Unknown VOI data type %d", voi_dtype));
3591 switch (vs->
stype) {
3608 case VS_STYPE_TDGST:
3613 KASSERT(0, (
"Unknown VOI stat type %d", vs->
stype));
3624 switch (voi_dtype) {
3625 case VSD_DTYPE_INT_S32:
3626 VSD(voistate, statevsd)->
prev.int32.s32 =
3629 case VSD_DTYPE_INT_U32:
3630 VSD(voistate, statevsd)->prev.int32.u32 =
3633 case VSD_DTYPE_INT_S64:
3634 VSD(voistate, statevsd)->prev.int64.s64 =
3637 case VSD_DTYPE_INT_U64:
3638 VSD(voistate, statevsd)->prev.int64.u64 =
3641 case VSD_DTYPE_INT_SLONG:
3642 VSD(voistate, statevsd)->prev.intlong.slong =
3643 voival->intlong.slong;
3645 case VSD_DTYPE_INT_ULONG:
3646 VSD(voistate, statevsd)->prev.intlong.ulong =
3647 voival->intlong.ulong;
3649 case VSD_DTYPE_Q_S32:
3651 &VSD(voistate, statevsd)->prev.q32.sq32,
3654 case VSD_DTYPE_Q_U32:
3656 &VSD(voistate, statevsd)->prev.q32.uq32,
3659 case VSD_DTYPE_Q_S64:
3661 &VSD(voistate, statevsd)->prev.q64.sq64,
3664 case VSD_DTYPE_Q_U64:
3666 &VSD(voistate, statevsd)->prev.q64.uq64,
3670 KASSERT(0, (
"Unknown VOI data type %d", voi_dtype));
3700 ntpl * (STATS_TPL_MAX_STR_SPEC_LEN + 1), SBUF_FIXEDLEN);
3705 for (i = 0; i <
ntpl; i++) {
3741 char kvpair_fmt[16], tplspec_fmt[16];
3742 char tpl_spec[STATS_TPL_MAX_STR_SPEC_LEN];
3743 char tpl_name[TPL_MAX_NAME_LEN + 2];
3744 stats_tpl_sr_cb_t subsys_cb;
3746 char *
buf, *new_rates_usr_str, *tpl_name_p;
3747 struct stats_tpl_sample_rate *rates;
3749 uint32_t cum_pct, pct, tpl_hash;
3750 int err, i, off, len, newlen, nrates;
3755 subsys_cb = (stats_tpl_sr_cb_t)arg1;
3756 KASSERT(subsys_cb != NULL, (
"%s: subsys_cb == arg1 == NULL", __func__));
3758 subsys_ctx =
malloc(arg2, M_TEMP, M_WAITOK | M_ZERO);
3763 err = subsys_cb(TPL_SR_UNLOCKED_GET, NULL, &nrates, subsys_ctx);
3768 len = max(req->newlen + 1, nrates * (STATS_TPL_MAX_STR_SPEC_LEN + 5));
3770 if (req->oldptr != NULL || req->newptr != NULL)
3773 if (req->oldptr != NULL) {
3776 err = SYSCTL_OUT(req,
"", 1);
3782 s =
sbuf_new(&_s,
buf, len, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
3785 err = subsys_cb(TPL_SR_RLOCKED_GET, &rates, &nrates,
3790 for (i = 0; i < nrates && !err; i++) {
3791 err =
sbuf_printf(s,
"%s\"%s\":%u=%u", i ?
"," :
"",
3792 tpllist[rates[i].tpl_slot_id]->mb->tplname,
3793 tpllist[rates[i].tpl_slot_id]->mb->tplhash,
3794 rates[i].tpl_sample_pct);
3798 err = subsys_cb(TPL_SR_RUNLOCK, &rates, &nrates, subsys_ctx);
3810 err = SYSCTL_OUT(req, NULL, len);
3814 if (err || req->newptr == NULL)
3817 newlen = req->newlen - req->newidx;
3818 err = SYSCTL_IN(req,
buf, newlen);
3835 sprintf(kvpair_fmt,
" %%%zu[^=]=%%u %%n",
sizeof(tpl_spec) - 1);
3836 sprintf(tplspec_fmt,
"%%%zu[^:]:%%u",
sizeof(tpl_name) - 1);
3847 cum_pct = nrates = 0;
3850 new_rates_usr_str =
buf;
3851 while (isspace(*new_rates_usr_str))
3852 new_rates_usr_str++;
3853 while (*new_rates_usr_str !=
'\0') {
3854 tpl_name_p = tpl_name;
3869 if (2 !=
sscanf(new_rates_usr_str, kvpair_fmt, tpl_spec, &pct,
3872 if ((1 >
sscanf(tpl_spec, tplspec_fmt, tpl_name, &tpl_hash)) &&
3873 (1 !=
sscanf(tpl_spec,
":%u", &tpl_hash)))
3875 if ((cum_pct += pct) > 100)
3880 len = strlen(tpl_name);
3882 if (tpl_name[len - 1] ==
'"')
3883 tpl_name[--len] =
'\0';
3884 if (tpl_name[0] ==
'"') {
3891 (nrates + 1) *
sizeof(*rates), M_WAITOK);
3892 rates[nrates].tpl_slot_id =
3894 if (rates[nrates].tpl_slot_id < 0) {
3895 err = -rates[nrates].tpl_slot_id;
3898 rates[nrates].tpl_sample_pct = pct;
3900 new_rates_usr_str += off;
3901 if (*new_rates_usr_str !=
',')
3903 new_rates_usr_str++;
3907 if ((new_rates_usr_str -
buf) < newlen) {
3915 err = subsys_cb(TPL_SR_PUT, &rates, &nrates,
3923 free(subsys_ctx, M_TEMP);
3931 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
3933 "list the name/hash of all available stats(9) templates");
3937static void __attribute__ ((constructor))
3938stats_constructor(
void)
3944static void __attribute__ ((destructor))
3945stats_destructor(
void)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void * realloc(void *addr, size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void panic(const char *fmt,...)
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
struct intr_irqsrc ** src
struct statsblob_tpl * tpl
struct voistatdata_numeric prev
int printf(const char *fmt,...)
int sprintf(char *buf, const char *cfmt,...)
int sbuf_finish(struct sbuf *s)
int sbuf_putc(struct sbuf *s, int c)
void sbuf_delete(struct sbuf *s)
int sbuf_printf(struct sbuf *s, const char *fmt,...)
ssize_t sbuf_len(struct sbuf *s)
char * sbuf_data(struct sbuf *s)
int sbuf_error(const struct sbuf *s)
struct sbuf * sbuf_new(struct sbuf *s, char *buf, int length, int flags)
int sbuf_cat(struct sbuf *s, const char *str)
int sscanf(const char *ibuf, const char *fmt,...)
static void stats_v1_itercb_tostr_freeform(struct statsblobv1 *sb, struct voi *v, struct voistat *vs, struct sb_iter_ctx *ctx)
int stats_v1_blob_snapshot(struct statsblobv1 **dst, size_t dstmaxsz, struct statsblobv1 *src, uint32_t flags)
static int stats_v1_voi_update_hist(enum vsd_dtype voi_dtype, struct voistatdata *voival, struct voistat *vs, struct voistatdata_hist *hist)
int stats_tpl_id2name(uint32_t tpl_id, char *buf, size_t len)
static int stats_v1_voi_update_max(enum vsd_dtype voi_dtype __unused, struct voistatdata *voival, struct voistat *vs, void *vsd)
int stats_vss_numeric_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, struct vss_numeric_hlpr_info *info)
static int stats_v1_vsd_tdgst_add(enum vsd_dtype vs_dtype, struct voistatdata_tdgst *tdgst, s64q_t x, uint64_t weight, int attempt)
static int stats_tpl_list_available(SYSCTL_HANDLER_ARGS)
const size_t vsd_dtype2size[VSD_NUM_DTYPES]
struct statsblobv1_tpl __aligned
static int ctd32cmp(const struct voistatdata_tdgstctd32 *c1, const struct voistatdata_tdgstctd32 *c2)
static void stats_tpl_update_hash(struct statsblob_tpl *tpl)
int stats_tpl_fetch(int tpl_id, struct statsblob_tpl **tpl)
int stats_v1_voistat_fetch_dptr(struct statsblobv1 *sb, int32_t voi_id, enum voi_stype stype, enum vsd_dtype *retdtype, struct voistatdata **retvsd, size_t *retvsdsz)
int(* stats_v1_blob_itercb_t)(struct statsblobv1 *sb, struct voi *v, struct voistat *vs, struct sb_iter_ctx *ctx)
static const bool vsd_compoundtype[VSD_NUM_DTYPES]
static int stats_v1_itercb_tostr(struct statsblobv1 *sb, struct voi *v, struct voistat *vs, struct sb_iter_ctx *ctx)
static void stats_voistatdata_tdgst_tostr(enum vsd_dtype voi_dtype __unused, const struct voistatdata_tdgst *tdgst, enum vsd_dtype tdgst_dtype, size_t tdgst_dsz __unused, enum sb_str_fmt fmt, struct sbuf *buf, int objdump)
#define BLOB_OFFSET(sb, off)
int stats_v1_blob_init(struct statsblobv1 *sb, uint32_t tpl_id, uint32_t flags)
const char * vs_stype2desc[VS_NUM_STYPES]
int stats_tpl_sample_rollthedice(struct stats_tpl_sample_rate *rates, int nrates, void *seed_bytes, size_t seed_len)
static uint64_t stats_pow_u64(uint64_t base, uint64_t exp)
static int stats_v1_voi_update_sum(enum vsd_dtype voi_dtype __unused, struct voistatdata *voival, struct voistat *vs, void *vsd)
static void stats_init(void *arg)
SYSINIT(stats, SI_SUB_KDTRACE, SI_ORDER_FIRST, stats_init, NULL)
int stats_tpl_sample_rates(SYSCTL_HANDLER_ARGS)
static int stats_v1_icb_reset_voistat(struct statsblobv1 *sb, struct voi *v __unused, struct voistat *vs, struct sb_iter_ctx *ctx __unused)
struct statsblobv1 * stats_v1_blob_alloc(uint32_t tpl_id, uint32_t flags __unused)
void stats_vss_hlpr_cleanup(uint32_t nvss, struct voistatspec *vss)
static struct statsblob_tpl ** tpllist
#define TPL_LIST_RUNLOCK()
static int stats_vss_hist_bkt_hlpr(struct vss_hist_hlpr_info *info, uint32_t curbkt, struct voistatdata_numeric *bkt_lb, struct voistatdata_numeric *bkt_ub)
int stats_vss_hlpr_init(enum vsd_dtype voi_dtype, uint32_t nvss, struct voistatspec *vss)
static void stats_v1_itercb_tostr_json(struct statsblobv1 *sb, struct voi *v, struct voistat *vs, struct sb_iter_ctx *ctx)
static uint32_t stats_vss_hist_nbkts_hlpr(struct vss_hist_hlpr_info *info)
const char * vs_stype2name[VS_NUM_STYPES]
static int stats_v1_blob_expand(struct statsblobv1 **sbpp, int newvoibytes, int newvoistatbytes, int newvoistatdatabytes)
int stats_vss_tdgst_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, struct vss_tdgst_hlpr_info *info)
static void * stats_realloc(void *ptr, size_t oldsz, size_t newsz, int flags)
static int stats_v1_itercb_visit(struct statsblobv1 *sb, struct voi *v, struct voistat *vs, struct sb_iter_ctx *ctx)
int stats_tpl_fetch_allocid(const char *name, uint32_t hash)
static void stats_v1_blob_iter(struct statsblobv1 *sb, stats_v1_blob_itercb_t icb, void *usrctx, uint32_t flags)
int stats_v1_blob_clone(struct statsblobv1 **dst, size_t dstmaxsz, struct statsblobv1 *src, uint32_t flags)
int stats_v1_voi_update(struct statsblobv1 *sb, int32_t voi_id, enum vsd_dtype voi_dtype, struct voistatdata *voival, uint32_t flags)
int stats_v1_blob_tostr(struct statsblobv1 *sb, struct sbuf *buf, enum sb_str_fmt fmt, uint32_t flags)
RW_SYSINIT(stats_tpl_list, &tpllistlock, "Stat template list lock")
static void stats_voistatdata_hist_tostr(enum vsd_dtype voi_dtype, const struct voistatdata_hist *hist, enum vsd_dtype hist_dtype, size_t hist_dsz, enum sb_str_fmt fmt, struct sbuf *buf, int objdump)
MALLOC_DEFINE(M_STATS, "stats(9) related memory", "stats(9) related memory")
void stats_v1_blob_destroy(struct statsblobv1 *sb)
ARB_GENERATE_STATIC(ctdth32, voistatdata_tdgstctd32, ctdlnk, ctd32cmp)
int stats_v1_tpl_add_voistats(uint32_t tpl_id, int32_t voi_id, const char *voi_name, enum vsd_dtype voi_dtype, uint32_t nvss, struct voistatspec *vss, uint32_t flags)
int stats_voistatdata_tostr(const struct voistatdata *vsd, enum vsd_dtype voi_dtype, enum vsd_dtype vsd_dtype, size_t vsd_sz, enum sb_str_fmt fmt, struct sbuf *buf, int objdump)
int stats_vss_hist_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, struct vss_hist_hlpr_info *info)
static int stats_v1_voi_update_tdgst(enum vsd_dtype voi_dtype, struct voistatdata *voival, struct voistat *vs, struct voistatdata_tdgst *tdgst)
static int ctd64cmp(const struct voistatdata_tdgstctd64 *c1, const struct voistatdata_tdgstctd64 *c2)
SYSCTL_NODE(_kern, OID_AUTO, stats, CTLFLAG_RW|CTLFLAG_MPSAFE, NULL, "stats(9) MIB")
int stats_v1_tpl_alloc(const char *name, uint32_t flags __unused)
_Static_assert(offsetof(struct statsblobv1, cursz)+SIZEOF_MEMBER(struct statsblobv1, cursz)==offsetof(struct statsblob, opaque), "statsblobv1 ABI mismatch")
static sbintime_t stats_sbinuptime(void)
#define TPL_LIST_RLOCK_ASSERT()
static char * stats_strdup(const char *s, int flags)
#define TPL_LIST_WUNLOCK()
static int stats_v1_blob_init_locked(struct statsblobv1 *sb, uint32_t tpl_id, uint32_t flags)
static void stats_v1_blob_finalise(struct statsblobv1 *sb __unused)
const struct voistatdata_numeric numeric_limits[2][VSD_DTYPE_Q_U64+1]
const char * vsd_dtype2name[VSD_NUM_DTYPES]
static struct rwlock tpllistlock
int stats_v1_blob_visit(struct statsblobv1 *sb, stats_blob_visitcb_t func, void *usrctx)
static int stats_v1_voi_update_min(enum vsd_dtype voi_dtype __unused, struct voistatdata *voival, struct voistat *vs, void *vsd)
static int stats_v1_vsd_tdgst_compress(enum vsd_dtype vs_dtype, struct voistatdata_tdgst *tdgst, int attempt)
#define TPL_LIST_WLOCK_ASSERT()
SYSCTL_PROC(_kern_stats, OID_AUTO, templates, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, stats_tpl_list_available, "A", "list the name/hash of all available stats(9) templates")
int copyout_nofault(const void *kaddr, void *udaddr, size_t len)