1 /*- 2 * Copyright (c) 2014-2018 Netflix, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 /* 30 * A kernel and user space statistics gathering API + infrastructure. 31 * 32 * Author: Lawrence Stewart <lstewart@netflix.com> 33 * 34 * Things to ponder: 35 * - Register callbacks for events e.g. counter stat passing a threshold 36 * 37 * - How could this become SIFTRv2? Perhaps publishing records to a ring 38 * mapped between userspace and kernel? 39 * 40 * - Potential stat types: 41 * RATE: events per unit time 42 * TIMESERIES: timestamped records. Stored in voistate? 43 * EWMA: Exponential weighted moving average. 44 * 45 * - How should second order stats work e.g. stat "A" depends on "B" 46 * 47 * - How do variable time windows work e.g. give me per-RTT stats 48 * 49 * - Should the API always require the caller to manage locking? Or should the 50 * API provide optional functionality to lock a blob during operations. 51 * 52 * - Should we continue to store unpacked naturally aligned structs in the 53 * blob or move to packed structs? Relates to inter-host 54 * serialisation/endian issues. 55 */ 56 57 #ifndef _SYS_STATS_H_ 58 #define _SYS_STATS_H_ 59 60 #include <sys/limits.h> 61 62 #ifndef _KERNEL 63 /* 64 * XXXLAS: Hacks to enable sharing template creation code between kernel and 65 * userland e.g. tcp_stats.c 66 */ 67 #define VNET(n) n 68 #define VNET_DEFINE(t, n) static t n __unused 69 #endif /* ! _KERNEL */ 70 71 #define TPL_MAX_NAME_LEN 64 72 73 /* 74 * The longest template string spec format i.e. the normative spec format, is: 75 * 76 * "<tplname>":<tplhash> 77 * 78 * Therefore, the max string length of a template string spec is: 79 * 80 * - TPL_MAX_NAME_LEN 81 * - 2 chars for "" 82 * - 1 char for : separating name and hash 83 * - 10 chars for 32bit hash 84 */ 85 #define STATS_TPL_MAX_STR_SPEC_LEN (TPL_MAX_NAME_LEN + 13) 86 87 struct sbuf; 88 struct sysctl_oid; 89 struct sysctl_req; 90 91 enum sb_str_fmt { 92 SB_STRFMT_FREEFORM = 0, 93 SB_STRFMT_JSON, 94 SB_STRFMT_NUM_FMTS /* +1 to highest numbered format type. */ 95 }; 96 97 /* VOI stat types. */ 98 enum voi_stype { 99 VS_STYPE_VOISTATE = 0, /* Reserved for internal API use. */ 100 VS_STYPE_SUM, 101 VS_STYPE_MAX, 102 VS_STYPE_MIN, 103 VS_STYPE_HIST, 104 VS_STYPE_TDGST, 105 VS_NUM_STYPES /* +1 to highest numbered stat type. */ 106 }; 107 108 /* 109 * VOI stat data types used as storage for certain stat types and to marshall 110 * data through various API calls. 111 */ 112 enum vsd_dtype { 113 VSD_DTYPE_VOISTATE = 0, /* Reserved for internal API use. */ 114 VSD_DTYPE_INT_S32, /* int32_t */ 115 VSD_DTYPE_INT_U32, /* uint32_t */ 116 VSD_DTYPE_INT_S64, /* int64_t */ 117 VSD_DTYPE_INT_U64, /* uint64_t */ 118 VSD_DTYPE_INT_SLONG, /* long */ 119 VSD_DTYPE_INT_ULONG, /* unsigned long */ 120 VSD_DTYPE_Q_S32, /* s32q_t */ 121 VSD_DTYPE_Q_U32, /* u32q_t */ 122 VSD_DTYPE_Q_S64, /* s64q_t */ 123 VSD_DTYPE_Q_U64, /* u64q_t */ 124 VSD_DTYPE_CRHIST32, /* continuous range histogram, 32bit buckets */ 125 VSD_DTYPE_DRHIST32, /* discrete range histogram, 32bit buckets */ 126 VSD_DTYPE_DVHIST32, /* discrete value histogram, 32bit buckets */ 127 VSD_DTYPE_CRHIST64, /* continuous range histogram, 64bit buckets */ 128 VSD_DTYPE_DRHIST64, /* discrete range histogram, 64bit buckets */ 129 VSD_DTYPE_DVHIST64, /* discrete value histogram, 64bit buckets */ 130 VSD_DTYPE_TDGSTCLUST32, /* clustering variant t-digest, 32bit buckets */ 131 VSD_DTYPE_TDGSTCLUST64, /* clustering variant t-digest, 64bit buckets */ 132 VSD_NUM_DTYPES /* +1 to highest numbered data type. */ 133 }; 134 135 struct voistatdata_int32 { 136 union { 137 int32_t s32; 138 uint32_t u32; 139 }; 140 }; 141 142 struct voistatdata_int64 { 143 union { 144 int64_t s64; 145 uint64_t u64; 146 //counter_u64_t u64pcpu; 147 }; 148 }; 149 150 struct voistatdata_intlong { 151 union { 152 long slong; 153 unsigned long ulong; 154 }; 155 }; 156 157 struct voistatdata_q32 { 158 union { 159 s32q_t sq32; 160 u32q_t uq32; 161 }; 162 }; 163 164 struct voistatdata_q64 { 165 union { 166 s64q_t sq64; 167 u64q_t uq64; 168 }; 169 }; 170 171 struct voistatdata_numeric { 172 union { 173 struct { 174 #if BYTE_ORDER == BIG_ENDIAN 175 uint32_t pad; 176 #endif 177 union { 178 int32_t s32; 179 uint32_t u32; 180 }; 181 #if BYTE_ORDER == LITTLE_ENDIAN 182 uint32_t pad; 183 #endif 184 } int32; 185 186 struct { 187 #if BYTE_ORDER == BIG_ENDIAN 188 uint32_t pad; 189 #endif 190 union { 191 s32q_t sq32; 192 u32q_t uq32; 193 }; 194 #if BYTE_ORDER == LITTLE_ENDIAN 195 uint32_t pad; 196 #endif 197 } q32; 198 199 struct { 200 #if BYTE_ORDER == BIG_ENDIAN && LONG_BIT == 32 201 uint32_t pad; 202 #endif 203 union { 204 long slong; 205 unsigned long ulong; 206 }; 207 #if BYTE_ORDER == LITTLE_ENDIAN && LONG_BIT == 32 208 uint32_t pad; 209 #endif 210 } intlong; 211 212 struct voistatdata_int64 int64; 213 struct voistatdata_q64 q64; 214 }; 215 }; 216 217 /* Continuous range histogram with 32bit buckets. */ 218 struct voistatdata_crhist32 { 219 uint32_t oob; 220 struct { 221 struct voistatdata_numeric lb; 222 uint32_t cnt; 223 } bkts[]; 224 }; 225 226 /* Continuous range histogram with 64bit buckets. */ 227 struct voistatdata_crhist64 { 228 uint64_t oob; 229 struct { 230 struct voistatdata_numeric lb; 231 uint64_t cnt; 232 } bkts[]; 233 }; 234 235 /* Discrete range histogram with 32bit buckets. */ 236 struct voistatdata_drhist32 { 237 uint32_t oob; 238 struct { 239 struct voistatdata_numeric lb, ub; 240 uint32_t cnt; 241 } bkts[]; 242 }; 243 244 /* Discrete range histogram with 64bit buckets. */ 245 struct voistatdata_drhist64 { 246 uint64_t oob; 247 struct { 248 struct voistatdata_numeric lb, ub; 249 uint64_t cnt; 250 } bkts[]; 251 }; 252 253 /* Discrete value histogram with 32bit buckets. */ 254 struct voistatdata_dvhist32 { 255 uint32_t oob; 256 struct { 257 struct voistatdata_numeric val; 258 uint32_t cnt; 259 } bkts[]; 260 }; 261 262 /* Discrete value histogram with 64bit buckets. */ 263 struct voistatdata_dvhist64 { 264 uint64_t oob; 265 struct { 266 struct voistatdata_numeric val; 267 uint64_t cnt; 268 } bkts[]; 269 }; 270 271 struct voistatdata_hist { 272 union { 273 struct voistatdata_crhist32 crhist32; 274 struct voistatdata_crhist64 crhist64; 275 struct voistatdata_dvhist32 dvhist32; 276 struct voistatdata_dvhist64 dvhist64; 277 struct voistatdata_drhist32 drhist32; 278 struct voistatdata_drhist64 drhist64; 279 }; 280 }; 281 282 struct voistatdata_tdgstctd32 { 283 ARB16_ENTRY() ctdlnk; 284 #ifdef DIAGNOSTIC 285 RB_ENTRY(voistatdata_tdgstctd32) rblnk; 286 #endif 287 s32q_t mu; 288 int32_t cnt; 289 }; 290 291 struct voistatdata_tdgstctd64 { 292 ARB16_ENTRY() ctdlnk; 293 #ifdef DIAGNOSTIC 294 RB_ENTRY(voistatdata_tdgstctd64) rblnk; 295 #endif 296 s64q_t mu; 297 int64_t cnt; 298 }; 299 300 struct voistatdata_tdgstctd { 301 union { 302 struct voistatdata_tdgstctd32 tdgstctd32; 303 struct voistatdata_tdgstctd64 tdgstctd64; 304 }; 305 }; 306 307 /* Clustering variant, fixed-point t-digest with 32bit mu/counts. */ 308 struct voistatdata_tdgstclust32 { 309 uint32_t smplcnt; /* Count of samples. */ 310 uint32_t compcnt; /* Count of digest compressions. */ 311 #ifdef DIAGNOSTIC 312 RB_HEAD(rbctdth32, voistatdata_tdgstctd32) rbctdtree; 313 #endif 314 /* Array-based red-black tree of centroids. */ 315 ARB16_HEAD(ctdth32, voistatdata_tdgstctd32) ctdtree; 316 }; 317 318 /* Clustering variant, fixed-point t-digest with 64bit mu/counts. */ 319 struct voistatdata_tdgstclust64 { 320 uint64_t smplcnt; /* Count of samples. */ 321 uint32_t compcnt; /* Count of digest compressions. */ 322 #ifdef DIAGNOSTIC 323 RB_HEAD(rbctdth64, voistatdata_tdgstctd64) rbctdtree; 324 #endif 325 /* Array-based red-black tree of centroids. */ 326 ARB16_HEAD(ctdth64, voistatdata_tdgstctd64) ctdtree; 327 }; 328 329 struct voistatdata_tdgst { 330 union { 331 struct voistatdata_tdgstclust32 tdgstclust32; 332 struct voistatdata_tdgstclust64 tdgstclust64; 333 }; 334 }; 335 336 struct voistatdata { 337 union { 338 struct voistatdata_int32 int32; 339 struct voistatdata_int64 int64; 340 struct voistatdata_intlong intlong; 341 struct voistatdata_q32 q32; 342 struct voistatdata_q64 q64; 343 struct voistatdata_crhist32 crhist32; 344 struct voistatdata_crhist64 crhist64; 345 struct voistatdata_dvhist32 dvhist32; 346 struct voistatdata_dvhist64 dvhist64; 347 struct voistatdata_drhist32 drhist32; 348 struct voistatdata_drhist64 drhist64; 349 struct voistatdata_tdgstclust32 tdgstclust32; 350 struct voistatdata_tdgstclust64 tdgstclust64; 351 }; 352 }; 353 354 #define VSD_HIST_LBOUND_INF 0x01 355 #define VSD_HIST_UBOUND_INF 0x02 356 struct vss_hist_hlpr_info { 357 enum hist_bkt_alloc { 358 BKT_LIN, /* Linear steps. */ 359 BKT_EXP, /* Exponential steps. */ 360 BKT_LINEXP, /* Exponential steps, linear sub-steps. */ 361 BKT_USR /* User specified buckets. */ 362 } scheme; 363 enum vsd_dtype voi_dtype; 364 enum vsd_dtype hist_dtype; 365 uint32_t flags; 366 struct voistatdata_numeric lb; 367 struct voistatdata_numeric ub; 368 union { 369 struct { 370 const uint64_t stepinc; 371 } lin; 372 struct { 373 const uint64_t stepbase; 374 const uint64_t stepexp; 375 } exp; 376 struct { 377 const uint64_t stepbase; 378 const uint64_t linstepdiv; 379 } linexp; 380 struct { 381 const uint16_t nbkts; 382 const struct { 383 struct voistatdata_numeric lb, ub; 384 } *bkts; 385 } usr; 386 }; 387 }; 388 389 struct vss_tdgst_hlpr_info { 390 enum vsd_dtype voi_dtype; 391 enum vsd_dtype tdgst_dtype; 392 uint32_t nctds; 393 uint32_t prec; 394 } __aligned(sizeof(void *)); 395 396 struct vss_numeric_hlpr_info { 397 uint32_t prec; 398 }; 399 400 struct vss_hlpr_info { 401 union { 402 struct vss_tdgst_hlpr_info tdgst; 403 struct vss_hist_hlpr_info hist; 404 struct vss_numeric_hlpr_info numeric; 405 }; 406 }; 407 408 struct voistatspec; 409 typedef int (*vss_hlpr_fn)(enum vsd_dtype, struct voistatspec *, 410 struct vss_hlpr_info *); 411 412 struct voistatspec { 413 vss_hlpr_fn hlpr; /* iv helper function. */ 414 struct vss_hlpr_info *hlprinfo; /* Helper function context. */ 415 struct voistatdata *iv; /* Initialisation value. */ 416 size_t vsdsz; /* Size of iv. */ 417 uint32_t flags; /* Stat flags. */ 418 enum vsd_dtype vs_dtype : 8; /* Stat's dtype. */ 419 enum voi_stype stype : 8; /* Stat type. */ 420 }; 421 422 extern const char *vs_stype2name[VS_NUM_STYPES]; 423 extern const char *vs_stype2desc[VS_NUM_STYPES]; 424 extern const char *vsd_dtype2name[VSD_NUM_DTYPES]; 425 extern const size_t vsd_dtype2size[VSD_NUM_DTYPES]; 426 #define LIM_MIN 0 427 #define LIM_MAX 1 428 extern const struct voistatdata_numeric numeric_limits[2][VSD_DTYPE_Q_U64 + 1]; 429 430 #define TYPEOF_MEMBER(type, member) __typeof(((type *)0)->member) 431 #define TYPEOF_MEMBER_PTR(type, member) __typeof(*(((type *)0)->member)) 432 #define SIZEOF_MEMBER(type, member) sizeof(TYPEOF_MEMBER(type, member)) 433 434 /* Cast a pointer to a voistatdata struct of requested type. */ 435 #define _VSD(cnst, type, ptr) ((cnst struct voistatdata_##type *)(ptr)) 436 #define VSD(type, ptr) _VSD(, type, ptr) 437 #define CONSTVSD(type, ptr) _VSD(const, type, ptr) 438 439 #define NVSS(vss_slots) (sizeof((vss_slots)) / sizeof(struct voistatspec)) 440 #define STATS_VSS(st, vsf, dt, hlp, hlpi) \ 441 ((struct voistatspec){ \ 442 .stype = (st), \ 443 .flags = (vsf), \ 444 .vs_dtype = (dt), \ 445 .hlpr = (hlp), \ 446 .hlprinfo = (hlpi), \ 447 }) 448 449 #define STATS_VSS_SUM() STATS_VSS(VS_STYPE_SUM, 0, 0, \ 450 (vss_hlpr_fn)&stats_vss_numeric_hlpr, NULL) 451 452 #define STATS_VSS_MAX() STATS_VSS(VS_STYPE_MAX, 0, 0, \ 453 (vss_hlpr_fn)&stats_vss_numeric_hlpr, NULL) 454 455 #define STATS_VSS_MIN() STATS_VSS(VS_STYPE_MIN, 0, 0, \ 456 (vss_hlpr_fn)&stats_vss_numeric_hlpr, NULL) 457 458 #define STATS_VSS_HIST(htype, hist_hlpr_info) STATS_VSS(VS_STYPE_HIST, 0, \ 459 htype, (vss_hlpr_fn)&stats_vss_hist_hlpr, \ 460 (struct vss_hlpr_info *)(hist_hlpr_info)) 461 462 #define STATS_VSS_TDIGEST(tdtype, tdgst_hlpr_info) STATS_VSS(VS_STYPE_TDGST, \ 463 0, tdtype, (vss_hlpr_fn)&stats_vss_tdgst_hlpr, \ 464 (struct vss_hlpr_info *)(tdgst_hlpr_info)) 465 466 #define TDGST_NCTRS2VSDSZ(tdtype, nctds) (sizeof(struct voistatdata_##tdtype) + \ 467 ((nctds) * sizeof(TYPEOF_MEMBER_PTR(struct voistatdata_##tdtype, \ 468 ctdtree.arb_nodes)))) 469 470 #define TDGST_HLPR_INFO(dt, nc, nf) \ 471 (&(struct vss_tdgst_hlpr_info){ \ 472 .tdgst_dtype = (dt), \ 473 .nctds = (nc), \ 474 .prec = (nf) \ 475 }) 476 477 #define STATS_VSS_TDGSTCLUST32(nctds, prec) \ 478 STATS_VSS_TDIGEST(VSD_DTYPE_TDGSTCLUST32, \ 479 TDGST_HLPR_INFO(VSD_DTYPE_TDGSTCLUST32, nctds, prec)) 480 481 #define STATS_VSS_TDGSTCLUST64(nctds, prec) \ 482 STATS_VSS_TDIGEST(VSD_DTYPE_TDGSTCLUST64, \ 483 TDGST_HLPR_INFO(VSD_DTYPE_TDGSTCLUST64, nctds, prec)) 484 485 #define HIST_VSDSZ2NBKTS(htype, dsz) \ 486 ((dsz - sizeof(struct voistatdata_##htype)) / \ 487 sizeof(TYPEOF_MEMBER(struct voistatdata_##htype, bkts[0]))) 488 489 #define HIST_NBKTS2VSDSZ(htype, nbkts) (sizeof(struct voistatdata_##htype) + \ 490 ((nbkts) * sizeof(TYPEOF_MEMBER_PTR(struct voistatdata_##htype, bkts)))) 491 492 #define HIST_HLPR_INFO_LIN_FIELDS(si) .lin.stepinc = (si) 493 494 #define HIST_HLPR_INFO_EXP_FIELDS(sb, se) \ 495 .exp.stepbase = (sb), .exp.stepexp = (se) 496 497 #define HIST_HLPR_INFO_LINEXP_FIELDS(nss, sb) \ 498 .linexp.linstepdiv = (nss), .linexp.stepbase = (sb) 499 500 #define HIST_HLPR_INFO_USR_FIELDS(bbs) \ 501 .usr.bkts = (TYPEOF_MEMBER(struct vss_hist_hlpr_info, usr.bkts))(bbs), \ 502 .usr.nbkts = (sizeof(bbs) / sizeof(struct voistatdata_numeric[2])) 503 504 #define HIST_HLPR_INFO(dt, sch, f, lbd, ubd, bkthlpr_fields) \ 505 (&(struct vss_hist_hlpr_info){ \ 506 .scheme = (sch), \ 507 .hist_dtype = (dt), \ 508 .flags = (f), \ 509 .lb = stats_ctor_vsd_numeric(lbd), \ 510 .ub = stats_ctor_vsd_numeric(ubd), \ 511 bkthlpr_fields \ 512 }) 513 514 #define STATS_VSS_CRHIST32_LIN(lb, ub, stepinc, vsdflags) \ 515 STATS_VSS_HIST(VSD_DTYPE_CRHIST32, HIST_HLPR_INFO(VSD_DTYPE_CRHIST32, \ 516 BKT_LIN, vsdflags, lb, ub, HIST_HLPR_INFO_LIN_FIELDS(stepinc))) 517 #define STATS_VSS_CRHIST64_LIN(lb, ub, stepinc, vsdflags) \ 518 STATS_VSS_HIST(VSD_DTYPE_CRHIST64, HIST_HLPR_INFO(VSD_DTYPE_CRHIST64, \ 519 BKT_LIN, vsdflags, lb, ub, HIST_HLPR_INFO_LIN_FIELDS(stepinc))) 520 521 #define STATS_VSS_CRHIST32_EXP(lb, ub, stepbase, stepexp, vsdflags) \ 522 STATS_VSS_HIST(VSD_DTYPE_CRHIST32, HIST_HLPR_INFO(VSD_DTYPE_CRHIST32, \ 523 BKT_EXP, vsdflags, lb, ub, HIST_HLPR_INFO_EXP_FIELDS(stepbase, stepexp))) 524 #define STATS_VSS_CRHIST64_EXP(lb, ub, stepbase, stepexp, vsdflags) \ 525 STATS_VSS_HIST(VSD_DTYPE_CRHIST64, HIST_HLPR_INFO(VSD_DTYPE_CRHIST64, \ 526 BKT_EXP, vsdflags, lb, ub, HIST_HLPR_INFO_EXP_FIELDS(stepbase, stepexp))) 527 528 #define STATS_VSS_CRHIST32_LINEXP(lb, ub, nlinsteps, stepbase, vsdflags) \ 529 STATS_VSS_HIST(VSD_DTYPE_CRHIST32, HIST_HLPR_INFO(VSD_DTYPE_CRHIST32, \ 530 BKT_LINEXP, vsdflags, lb, ub, HIST_HLPR_INFO_LINEXP_FIELDS(nlinsteps, \ 531 stepbase))) 532 #define STATS_VSS_CRHIST64_LINEXP(lb, ub, nlinsteps, stepbase, vsdflags) \ 533 STATS_VSS_HIST(VSD_DTYPE_CRHIST64, HIST_HLPR_INFO(VSD_DTYPE_CRHIST64, \ 534 BKT_LINEXP, vsdflags, lb, ub, HIST_HLPR_INFO_LINEXP_FIELDS(nlinsteps, \ 535 stepbase))) 536 537 #define STATS_VSS_CRHIST32_USR(bkts, vsdflags) \ 538 STATS_VSS_HIST(VSD_DTYPE_CRHIST32, HIST_HLPR_INFO(VSD_DTYPE_CRHIST32, \ 539 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(bkts))) 540 #define STATS_VSS_CRHIST64_USR(bkts, vsdflags) \ 541 STATS_VSS_HIST(VSD_DTYPE_CRHIST64, HIST_HLPR_INFO(VSD_DTYPE_CRHIST64, \ 542 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(bkts))) 543 544 #define STATS_VSS_DRHIST32_USR(bkts, vsdflags) \ 545 STATS_VSS_HIST(VSD_DTYPE_DRHIST32, HIST_HLPR_INFO(VSD_DTYPE_DRHIST32, \ 546 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(bkts))) 547 #define STATS_VSS_DRHIST64_USR(bkts, vsdflags) \ 548 STATS_VSS_HIST(VSD_DTYPE_DRHIST64, HIST_HLPR_INFO(VSD_DTYPE_DRHIST64, \ 549 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(bkts))) 550 551 #define STATS_VSS_DVHIST32_USR(vals, vsdflags) \ 552 STATS_VSS_HIST(VSD_DTYPE_DVHIST32, HIST_HLPR_INFO(VSD_DTYPE_DVHIST32, \ 553 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(vals))) 554 #define STATS_VSS_DVHIST64_USR(vals, vsdflags) \ 555 STATS_VSS_HIST(VSD_DTYPE_DVHIST64, HIST_HLPR_INFO(VSD_DTYPE_DVHIST64, \ 556 BKT_USR, vsdflags, 0, 0, HIST_HLPR_INFO_USR_FIELDS(vals))) 557 558 #define DRBKT(lb, ub) { stats_ctor_vsd_numeric(lb), stats_ctor_vsd_numeric(ub) } 559 #define DVBKT(val) DRBKT(val, val) 560 #define CRBKT(lb) DRBKT(lb, lb) 561 #define HBKTS(...) ((struct voistatdata_numeric [][2]){__VA_ARGS__}) 562 563 #define VSD_HIST_FIELD(hist, cnst, hist_dtype, op, field) \ 564 (VSD_DTYPE_CRHIST32 == (hist_dtype) ? \ 565 op(_VSD(cnst, crhist32, hist)->field) : \ 566 (VSD_DTYPE_DRHIST32 == (hist_dtype) ? \ 567 op(_VSD(cnst, drhist32, hist)->field) : \ 568 (VSD_DTYPE_DVHIST32 == (hist_dtype) ? \ 569 op(_VSD(cnst, dvhist32, hist)->field) : \ 570 (VSD_DTYPE_CRHIST64 == (hist_dtype) ? \ 571 op(_VSD(cnst, crhist64, hist)->field) : \ 572 (VSD_DTYPE_DRHIST64 == (hist_dtype) ? \ 573 op(_VSD(cnst, drhist64, hist)->field) : \ 574 (op(_VSD(cnst, dvhist64, hist)->field))))))) 575 #define VSD_HIST_FIELDVAL(hist, hist_dtype, field) \ 576 VSD_HIST_FIELD(hist, , hist_dtype, ,field) 577 #define VSD_CONSTHIST_FIELDVAL(hist, hist_dtype, field) \ 578 VSD_HIST_FIELD(hist, const, hist_dtype, ,field) 579 #define VSD_HIST_FIELDPTR(hist, hist_dtype, field) \ 580 VSD_HIST_FIELD(hist, , hist_dtype, (void *)&,field) 581 #define VSD_CONSTHIST_FIELDPTR(hist, hist_dtype, field) \ 582 VSD_HIST_FIELD(hist, const, hist_dtype, (void *)&,field) 583 584 #define VSD_CRHIST_FIELD(hist, cnst, hist_dtype, op, field) \ 585 (VSD_DTYPE_CRHIST32 == (hist_dtype) ? \ 586 op(_VSD(cnst, crhist32, hist)->field) : \ 587 op(_VSD(cnst, crhist64, hist)->field)) 588 #define VSD_CRHIST_FIELDVAL(hist, hist_dtype, field) \ 589 VSD_CRHIST_FIELD(hist, , hist_dtype, , field) 590 #define VSD_CONSTCRHIST_FIELDVAL(hist, hist_dtype, field) \ 591 VSD_CRHIST_FIELD(hist, const, hist_dtype, , field) 592 #define VSD_CRHIST_FIELDPTR(hist, hist_dtype, field) \ 593 VSD_CRHIST_FIELD(hist, , hist_dtype, &, field) 594 #define VSD_CONSTCRHIST_FIELDPTR(hist, hist_dtype, field) \ 595 VSD_CRHIST_FIELD(hist, const, hist_dtype, &, field) 596 597 #define VSD_DRHIST_FIELD(hist, cnst, hist_dtype, op, field) \ 598 (VSD_DTYPE_DRHIST32 == (hist_dtype) ? \ 599 op(_VSD(cnst, drhist32, hist)->field) : \ 600 op(_VSD(cnst, drhist64, hist)->field)) 601 #define VSD_DRHIST_FIELDVAL(hist, hist_dtype, field) \ 602 VSD_DRHIST_FIELD(hist, , hist_dtype, , field) 603 #define VSD_CONSTDRHIST_FIELDVAL(hist, hist_dtype, field) \ 604 VSD_DRHIST_FIELD(hist, const, hist_dtype, , field) 605 #define VSD_DRHIST_FIELDPTR(hist, hist_dtype, field) \ 606 VSD_DRHIST_FIELD(hist, , hist_dtype, &, field) 607 #define VSD_CONSTDRHIST_FIELDPTR(hist, hist_dtype, field) \ 608 VSD_DRHIST_FIELD(hist, const, hist_dtype, &, field) 609 610 #define VSD_DVHIST_FIELD(hist, cnst, hist_dtype, op, field) \ 611 (VSD_DTYPE_DVHIST32 == (hist_dtype) ? \ 612 op(_VSD(cnst, dvhist32, hist)->field) : \ 613 op(_VSD(cnst, dvhist64, hist)->field)) 614 #define VSD_DVHIST_FIELDVAL(hist, hist_dtype, field) \ 615 VSD_DVHIST_FIELD(hist, , hist_dtype, , field) 616 #define VSD_CONSTDVHIST_FIELDVAL(hist, hist_dtype, field) \ 617 VSD_DVHIST_FIELD(hist, const, hist_dtype, , field) 618 #define VSD_DVHIST_FIELDPTR(hist, hist_dtype, field) \ 619 VSD_DVHIST_FIELD(hist, , hist_dtype, &, field) 620 #define VSD_CONSTDVHIST_FIELDPTR(hist, hist_dtype, field) \ 621 VSD_DVHIST_FIELD(hist, const, hist_dtype, &, field) 622 623 #define STATS_ABI_V1 1 624 struct statsblobv1; 625 626 enum sb_endianness { 627 SB_UE = 0, /* Unknown endian. */ 628 SB_LE, /* Little endian. */ 629 SB_BE /* Big endian. */ 630 }; 631 632 struct statsblob { 633 uint8_t abi; 634 uint8_t endian; 635 uint16_t flags; 636 uint16_t maxsz; 637 uint16_t cursz; 638 uint8_t opaque[]; 639 } __aligned(sizeof(void *)); 640 641 struct metablob { 642 char *tplname; 643 uint32_t tplhash; 644 struct voi_meta { 645 char *name; 646 char *desc; 647 } *voi_meta; 648 }; 649 650 struct statsblob_tpl { 651 struct metablob *mb; /* Template metadata */ 652 struct statsblob *sb; /* Template schema */ 653 }; 654 655 struct stats_tpl_sample_rate { 656 /* XXXLAS: Storing slot_id assumes templates are never removed. */ 657 int32_t tpl_slot_id; 658 uint32_t tpl_sample_pct; 659 }; 660 661 /* Template sample rates list management callback actions. */ 662 enum stats_tpl_sr_cb_action { 663 TPL_SR_UNLOCKED_GET, 664 TPL_SR_RLOCKED_GET, 665 TPL_SR_RUNLOCK, 666 TPL_SR_PUT 667 }; 668 669 /* 670 * Callback function pointer passed as arg1 to stats_tpl_sample_rates(). ctx is 671 * a heap-allocated, zero-initialised blob of contextual memory valid during a 672 * single stats_tpl_sample_rates() call and sized per the value passed as arg2. 673 * Returns 0 on success, an errno on error. 674 * - When called with "action == TPL_SR_*_GET", return the subsystem's rates 675 * list ptr and count, locked or unlocked as requested. 676 * - When called with "action == TPL_SR_RUNLOCK", unlock the subsystem's rates 677 * list ptr and count. Pair with a prior "action == TPL_SR_RLOCKED_GET" call. 678 * - When called with "action == TPL_SR_PUT, update the subsystem's rates list 679 * ptr and count to the sysctl processed values and return the inactive list 680 * details in rates/nrates for garbage collection by stats_tpl_sample_rates(). 681 */ 682 typedef int (*stats_tpl_sr_cb_t)(enum stats_tpl_sr_cb_action action, 683 struct stats_tpl_sample_rate **rates, int *nrates, void *ctx); 684 685 /* Flags related to iterating over a stats blob. */ 686 #define SB_IT_FIRST_CB 0x0001 687 #define SB_IT_LAST_CB 0x0002 688 #define SB_IT_FIRST_VOI 0x0004 689 #define SB_IT_LAST_VOI 0x0008 690 #define SB_IT_FIRST_VOISTAT 0x0010 691 #define SB_IT_LAST_VOISTAT 0x0020 692 #define SB_IT_NULLVOI 0x0040 693 #define SB_IT_NULLVOISTAT 0x0080 694 695 struct sb_visit { 696 struct voistatdata *vs_data; 697 uint32_t tplhash; 698 uint32_t flags; 699 int16_t voi_id; 700 int16_t vs_dsz; 701 uint16_t vs_errs; 702 enum vsd_dtype voi_dtype : 8; 703 enum vsd_dtype vs_dtype : 8; 704 int8_t vs_stype; 705 }; 706 707 /* Stats blob iterator callback called for each struct voi. */ 708 typedef int (*stats_blob_visitcb_t)(struct sb_visit *sbv, void *usrctx); 709 710 /* ABI specific functions. */ 711 int stats_v1_tpl_alloc(const char *name, uint32_t flags); 712 int stats_v1_tpl_add_voistats(uint32_t tpl_id, int32_t voi_id, 713 const char *voi_name, enum vsd_dtype voi_dtype, uint32_t nvss, 714 struct voistatspec *vss, uint32_t flags); 715 int stats_v1_blob_init(struct statsblobv1 *sb, uint32_t tpl_id, uint32_t flags); 716 struct statsblobv1 * stats_v1_blob_alloc(uint32_t tpl_id, uint32_t flags); 717 int stats_v1_blob_clone(struct statsblobv1 **dst, size_t dstmaxsz, 718 struct statsblobv1 *src, uint32_t flags); 719 void stats_v1_blob_destroy(struct statsblobv1 *sb); 720 #define SB_CLONE_RSTSRC 0x0001 /* Reset src blob if clone successful. */ 721 #define SB_CLONE_ALLOCDST 0x0002 /* Allocate src->cursz memory for dst. */ 722 #define SB_CLONE_USRDSTNOFAULT 0x0004 /* Clone to wired userspace dst. */ 723 #define SB_CLONE_USRDST 0x0008 /* Clone to unwired userspace dst. */ 724 int stats_v1_blob_snapshot(struct statsblobv1 **dst, size_t dstmaxsz, 725 struct statsblobv1 *src, uint32_t flags); 726 #define SB_TOSTR_OBJDUMP 0x00000001 727 #define SB_TOSTR_META 0x00000002 /* Lookup metablob and render metadata */ 728 int stats_v1_blob_tostr(struct statsblobv1 *sb, struct sbuf *buf, 729 enum sb_str_fmt fmt, uint32_t flags); 730 int stats_v1_blob_visit(struct statsblobv1 *sb, stats_blob_visitcb_t func, 731 void *usrctx); 732 /* VOI related function flags. */ 733 #define SB_VOI_RELUPDATE 0x00000001 /* voival is relative to previous value. */ 734 int stats_v1_voi_update(struct statsblobv1 *sb, int32_t voi_id, 735 enum vsd_dtype voi_dtype, struct voistatdata *voival, uint32_t flags); 736 int stats_v1_voistat_fetch_dptr(struct statsblobv1 *sb, int32_t voi_id, 737 enum voi_stype stype, enum vsd_dtype *retdtype, struct voistatdata **retvsd, 738 size_t *retvsdsz); 739 740 /* End ABI specific functions. */ 741 742 /* ABI agnostic functions. */ 743 int stats_vss_hlpr_init(enum vsd_dtype voi_dtype, uint32_t nvss, 744 struct voistatspec *vss); 745 void stats_vss_hlpr_cleanup(uint32_t nvss, struct voistatspec *vss); 746 int stats_vss_hist_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, 747 struct vss_hist_hlpr_info *info); 748 int stats_vss_numeric_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, 749 struct vss_numeric_hlpr_info *info); 750 int stats_vss_tdgst_hlpr(enum vsd_dtype voi_dtype, struct voistatspec *vss, 751 struct vss_tdgst_hlpr_info *info); 752 int stats_tpl_fetch(int tpl_id, struct statsblob_tpl **tpl); 753 int stats_tpl_fetch_allocid(const char *name, uint32_t hash); 754 int stats_tpl_id2name(uint32_t tpl_id, char *buf, size_t len); 755 int stats_tpl_sample_rates(struct sysctl_oid *oidp, void *arg1, intmax_t arg2, 756 struct sysctl_req *req); 757 int stats_tpl_sample_rollthedice(struct stats_tpl_sample_rate *rates, 758 int nrates, void *seed_bytes, size_t seed_len); 759 int stats_voistatdata_tostr(const struct voistatdata *vsd, 760 enum vsd_dtype voi_dtype, enum vsd_dtype vsd_dtype, size_t vsd_sz, 761 enum sb_str_fmt fmt, struct sbuf *buf, int objdump); 762 763 static inline struct voistatdata_numeric 764 stats_ctor_vsd_numeric(uint64_t val) 765 { 766 struct voistatdata_numeric tmp; 767 768 tmp.int64.u64 = val; 769 770 return (tmp); 771 } 772 773 static inline int 774 stats_tpl_alloc(const char *name, uint32_t flags) 775 { 776 777 return (stats_v1_tpl_alloc(name, flags)); 778 } 779 780 static inline int 781 stats_tpl_add_voistats(uint32_t tpl_id, int32_t voi_id, const char *voi_name, 782 enum vsd_dtype voi_dtype, uint32_t nvss, struct voistatspec *vss, 783 uint32_t flags) 784 { 785 int ret; 786 787 if ((ret = stats_vss_hlpr_init(voi_dtype, nvss, vss)) == 0) { 788 ret = stats_v1_tpl_add_voistats(tpl_id, voi_id, voi_name, 789 voi_dtype, nvss, vss, flags); 790 } 791 stats_vss_hlpr_cleanup(nvss, vss); 792 793 return (ret); 794 } 795 796 static inline int 797 stats_blob_init(struct statsblob *sb, uint32_t tpl_id, uint32_t flags) 798 { 799 800 return (stats_v1_blob_init((struct statsblobv1 *)sb, tpl_id, flags)); 801 } 802 803 static inline struct statsblob * 804 stats_blob_alloc(uint32_t tpl_id, uint32_t flags) 805 { 806 807 return ((struct statsblob *)stats_v1_blob_alloc(tpl_id, flags)); 808 } 809 810 static inline int 811 stats_blob_clone(struct statsblob **dst, size_t dstmaxsz, struct statsblob *src, 812 uint32_t flags) 813 { 814 815 return (stats_v1_blob_clone((struct statsblobv1 **)dst, dstmaxsz, 816 (struct statsblobv1 *)src, flags)); 817 } 818 819 static inline void 820 stats_blob_destroy(struct statsblob *sb) 821 { 822 823 stats_v1_blob_destroy((struct statsblobv1 *)sb); 824 } 825 826 static inline int 827 stats_blob_visit(struct statsblob *sb, stats_blob_visitcb_t func, void *usrctx) 828 { 829 830 return (stats_v1_blob_visit((struct statsblobv1 *)sb, func, usrctx)); 831 } 832 833 static inline int 834 stats_blob_tostr(struct statsblob *sb, struct sbuf *buf, 835 enum sb_str_fmt fmt, uint32_t flags) 836 { 837 838 return (stats_v1_blob_tostr((struct statsblobv1 *)sb, buf, fmt, flags)); 839 } 840 841 static inline int 842 stats_voistat_fetch_dptr(struct statsblob *sb, int32_t voi_id, 843 enum voi_stype stype, enum vsd_dtype *retdtype, struct voistatdata **retvsd, 844 size_t *retvsdsz) 845 { 846 847 return (stats_v1_voistat_fetch_dptr((struct statsblobv1 *)sb, 848 voi_id, stype, retdtype, retvsd, retvsdsz)); 849 } 850 851 static inline int 852 stats_voistat_fetch_s64(struct statsblob *sb, int32_t voi_id, 853 enum voi_stype stype, int64_t *ret) 854 { 855 struct voistatdata *vsd; 856 enum vsd_dtype vs_dtype; 857 int error; 858 859 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 860 NULL))) 861 return (error); 862 else if (VSD_DTYPE_INT_S64 != vs_dtype) 863 return (EFTYPE); 864 865 *ret = vsd->int64.s64; 866 return (0); 867 } 868 869 static inline int 870 stats_voistat_fetch_u64(struct statsblob *sb, int32_t voi_id, 871 enum voi_stype stype, uint64_t *ret) 872 { 873 struct voistatdata *vsd; 874 enum vsd_dtype vs_dtype; 875 int error; 876 877 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 878 NULL))) 879 return (error); 880 else if (VSD_DTYPE_INT_U64 != vs_dtype) 881 return (EFTYPE); 882 883 *ret = vsd->int64.u64; 884 return (0); 885 } 886 887 static inline int 888 stats_voistat_fetch_s32(struct statsblob *sb, int32_t voi_id, 889 enum voi_stype stype, int32_t *ret) 890 { 891 struct voistatdata *vsd; 892 enum vsd_dtype vs_dtype; 893 int error; 894 895 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 896 NULL))) 897 return (error); 898 else if (VSD_DTYPE_INT_S32 != vs_dtype) 899 return (EFTYPE); 900 901 *ret = vsd->int32.s32; 902 return (0); 903 } 904 905 static inline int 906 stats_voistat_fetch_u32(struct statsblob *sb, int32_t voi_id, 907 enum voi_stype stype, uint32_t *ret) 908 { 909 struct voistatdata *vsd; 910 enum vsd_dtype vs_dtype; 911 int error; 912 913 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 914 NULL))) 915 return (error); 916 else if (VSD_DTYPE_INT_U32 != vs_dtype) 917 return (EFTYPE); 918 919 *ret = vsd->int32.u32; 920 return (0); 921 } 922 923 static inline int 924 stats_voistat_fetch_slong(struct statsblob *sb, int32_t voi_id, 925 enum voi_stype stype, long *ret) 926 { 927 struct voistatdata *vsd; 928 enum vsd_dtype vs_dtype; 929 int error; 930 931 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 932 NULL))) 933 return (error); 934 else if (VSD_DTYPE_INT_SLONG != vs_dtype) 935 return (EFTYPE); 936 937 *ret = vsd->intlong.slong; 938 return (0); 939 } 940 941 static inline int 942 stats_voistat_fetch_ulong(struct statsblob *sb, int32_t voi_id, 943 enum voi_stype stype, unsigned long *ret) 944 { 945 struct voistatdata *vsd; 946 enum vsd_dtype vs_dtype; 947 int error; 948 949 if ((error = stats_voistat_fetch_dptr(sb, voi_id, stype, &vs_dtype, &vsd, 950 NULL))) 951 return (error); 952 else if (VSD_DTYPE_INT_ULONG != vs_dtype) 953 return (EFTYPE); 954 955 *ret = vsd->intlong.ulong; 956 return (0); 957 } 958 959 static inline int 960 stats_blob_snapshot(struct statsblob **dst, size_t dstmaxsz, 961 struct statsblob *src, uint32_t flags) 962 { 963 964 return (stats_v1_blob_snapshot((struct statsblobv1 **)dst, dstmaxsz, 965 (struct statsblobv1 *)src, flags)); 966 } 967 968 static inline int 969 stats_voi_update_abs_s32(struct statsblob *sb, int32_t voi_id, int32_t voival) 970 { 971 972 if (sb == NULL) 973 return (0); 974 975 struct voistatdata tmp; 976 tmp.int32.s32 = voival; 977 978 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 979 VSD_DTYPE_INT_S32, &tmp, 0)); 980 } 981 982 static inline int 983 stats_voi_update_rel_s32(struct statsblob *sb, int32_t voi_id, int32_t voival) 984 { 985 986 if (sb == NULL) 987 return (0); 988 989 struct voistatdata tmp; 990 tmp.int32.s32 = voival; 991 992 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 993 VSD_DTYPE_INT_S32, &tmp, SB_VOI_RELUPDATE)); 994 } 995 996 static inline int 997 stats_voi_update_abs_u32(struct statsblob *sb, int32_t voi_id, uint32_t voival) 998 { 999 1000 if (sb == NULL) 1001 return (0); 1002 1003 struct voistatdata tmp; 1004 tmp.int32.u32 = voival; 1005 1006 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1007 VSD_DTYPE_INT_U32, &tmp, 0)); 1008 } 1009 1010 static inline int 1011 stats_voi_update_rel_u32(struct statsblob *sb, int32_t voi_id, uint32_t voival) 1012 { 1013 1014 if (sb == NULL) 1015 return (0); 1016 1017 struct voistatdata tmp; 1018 tmp.int32.u32 = voival; 1019 1020 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1021 VSD_DTYPE_INT_U32, &tmp, SB_VOI_RELUPDATE)); 1022 } 1023 1024 static inline int 1025 stats_voi_update_abs_s64(struct statsblob *sb, int32_t voi_id, int64_t voival) 1026 { 1027 1028 if (sb == NULL) 1029 return (0); 1030 1031 struct voistatdata tmp; 1032 tmp.int64.s64 = voival; 1033 1034 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1035 VSD_DTYPE_INT_S64, &tmp, 0)); 1036 } 1037 1038 static inline int 1039 stats_voi_update_rel_s64(struct statsblob *sb, int32_t voi_id, int64_t voival) 1040 { 1041 1042 if (sb == NULL) 1043 return (0); 1044 1045 struct voistatdata tmp; 1046 tmp.int64.s64 = voival; 1047 1048 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1049 VSD_DTYPE_INT_S64, &tmp, SB_VOI_RELUPDATE)); 1050 } 1051 1052 static inline int 1053 stats_voi_update_abs_u64(struct statsblob *sb, int32_t voi_id, uint64_t voival) 1054 { 1055 1056 if (sb == NULL) 1057 return (0); 1058 1059 struct voistatdata tmp; 1060 tmp.int64.u64 = voival; 1061 1062 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1063 VSD_DTYPE_INT_U64, &tmp, 0)); 1064 } 1065 1066 static inline int 1067 stats_voi_update_rel_u64(struct statsblob *sb, int32_t voi_id, uint64_t voival) 1068 { 1069 1070 if (sb == NULL) 1071 return (0); 1072 1073 struct voistatdata tmp; 1074 tmp.int64.u64 = voival; 1075 1076 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1077 VSD_DTYPE_INT_U64, &tmp, SB_VOI_RELUPDATE)); 1078 } 1079 1080 static inline int 1081 stats_voi_update_abs_slong(struct statsblob *sb, int32_t voi_id, long voival) 1082 { 1083 1084 if (sb == NULL) 1085 return (0); 1086 1087 struct voistatdata tmp; 1088 tmp.intlong.slong = voival; 1089 1090 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1091 VSD_DTYPE_INT_SLONG, &tmp, 0)); 1092 } 1093 1094 static inline int 1095 stats_voi_update_rel_slong(struct statsblob *sb, int32_t voi_id, long voival) 1096 { 1097 1098 if (sb == NULL) 1099 return (0); 1100 1101 struct voistatdata tmp; 1102 tmp.intlong.slong = voival; 1103 1104 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1105 VSD_DTYPE_INT_SLONG, &tmp, SB_VOI_RELUPDATE)); 1106 } 1107 1108 static inline int 1109 stats_voi_update_abs_ulong(struct statsblob *sb, int32_t voi_id, 1110 unsigned long voival) 1111 { 1112 1113 if (sb == NULL) 1114 return (0); 1115 1116 struct voistatdata tmp; 1117 tmp.intlong.ulong = voival; 1118 1119 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1120 VSD_DTYPE_INT_ULONG, &tmp, 0)); 1121 } 1122 1123 static inline int 1124 stats_voi_update_rel_ulong(struct statsblob *sb, int32_t voi_id, 1125 unsigned long voival) 1126 { 1127 1128 if (sb == NULL) 1129 return (0); 1130 1131 struct voistatdata tmp; 1132 tmp.intlong.ulong = voival; 1133 1134 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1135 VSD_DTYPE_INT_ULONG, &tmp, SB_VOI_RELUPDATE)); 1136 } 1137 1138 static inline int 1139 stats_voi_update_abs_sq32(struct statsblob *sb, int32_t voi_id, s32q_t voival) 1140 { 1141 1142 if (sb == NULL) 1143 return (0); 1144 1145 struct voistatdata tmp; 1146 tmp.q32.sq32 = voival; 1147 1148 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1149 VSD_DTYPE_Q_S32, &tmp, 0)); 1150 } 1151 1152 static inline int 1153 stats_voi_update_rel_sq32(struct statsblob *sb, int32_t voi_id, s32q_t voival) 1154 { 1155 1156 if (sb == NULL) 1157 return (0); 1158 1159 struct voistatdata tmp; 1160 tmp.q32.sq32 = voival; 1161 1162 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1163 VSD_DTYPE_Q_S32, &tmp, SB_VOI_RELUPDATE)); 1164 } 1165 1166 static inline int 1167 stats_voi_update_abs_uq32(struct statsblob *sb, int32_t voi_id, u32q_t voival) 1168 { 1169 1170 if (sb == NULL) 1171 return (0); 1172 1173 struct voistatdata tmp; 1174 tmp.q32.uq32 = voival; 1175 1176 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1177 VSD_DTYPE_Q_U32, &tmp, 0)); 1178 } 1179 1180 static inline int 1181 stats_voi_update_rel_uq32(struct statsblob *sb, int32_t voi_id, u32q_t voival) 1182 { 1183 1184 if (sb == NULL) 1185 return (0); 1186 1187 struct voistatdata tmp; 1188 tmp.q32.uq32 = voival; 1189 1190 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1191 VSD_DTYPE_Q_U32, &tmp, SB_VOI_RELUPDATE)); 1192 } 1193 1194 static inline int 1195 stats_voi_update_abs_sq64(struct statsblob *sb, int32_t voi_id, s64q_t voival) 1196 { 1197 1198 if (sb == NULL) 1199 return (0); 1200 1201 struct voistatdata tmp; 1202 tmp.q64.sq64 = voival; 1203 1204 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1205 VSD_DTYPE_Q_S64, &tmp, 0)); 1206 } 1207 1208 static inline int 1209 stats_voi_update_rel_sq64(struct statsblob *sb, int32_t voi_id, s64q_t voival) 1210 { 1211 1212 if (sb == NULL) 1213 return (0); 1214 1215 struct voistatdata tmp; 1216 tmp.q64.sq64 = voival; 1217 1218 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1219 VSD_DTYPE_Q_S64, &tmp, SB_VOI_RELUPDATE)); 1220 } 1221 1222 static inline int 1223 stats_voi_update_abs_uq64(struct statsblob *sb, int32_t voi_id, u64q_t voival) 1224 { 1225 1226 if (sb == NULL) 1227 return (0); 1228 1229 struct voistatdata tmp; 1230 tmp.q64.uq64 = voival; 1231 1232 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1233 VSD_DTYPE_Q_U64, &tmp, 0)); 1234 } 1235 1236 static inline int 1237 stats_voi_update_rel_uq64(struct statsblob *sb, int32_t voi_id, u64q_t voival) 1238 { 1239 1240 if (sb == NULL) 1241 return (0); 1242 1243 struct voistatdata tmp; 1244 tmp.q64.uq64 = voival; 1245 1246 return (stats_v1_voi_update((struct statsblobv1 *)sb, voi_id, 1247 VSD_DTYPE_Q_U64, &tmp, SB_VOI_RELUPDATE)); 1248 } 1249 1250 /* End ABI agnostic functions. */ 1251 1252 #endif /* _SYS_STATS_H_ */ 1253