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