Lines Matching +full:c +full:- +full:define +full:- +full:name

1 // SPDX-License-Identifier: BSD-2-Clause
3 * This single-header library defines a collection of variadic macros for
4 * defining and triggering USDTs (User Statically-Defined Tracepoints):
6 * - For USDTs without associated semaphore:
7 * USDT(group, name, args...)
9 * - For USDTs with implicit (transparent to the user) semaphore:
10 * USDT_WITH_SEMA(group, name, args...)
11 * USDT_IS_ACTIVE(group, name)
13 * - For USDTs with explicit (user-defined and provided) semaphore:
14 * USDT_WITH_EXPLICIT_SEMA(sema, group, name, args...)
19 * a combination of `group` and `name` identifiers, which is used by external
22 * USDTs can have an associated (2-byte) activity counter (USDT semaphore),
24 * BPF-based tracer is attached to the USDT. This USDT semaphore can be used
38 * Tracing tools (bpftrace and BPF-based tracers, systemtap, etc) insert
39 * breakpoints on top of the nop, and decode the location operand-strings,
43 * They are constrained by inline-assembler codes.The default is:
45 * #define USDT_ARG_CONSTRAINT nor
54 * #define USDT_ARG_CONSTRAINT g
58 * library and generally recognized and assumed by BPF-based tracing tools)
66 * USDT definitions are fully binary compatible and any USDT-based tooling
70 * [0] https://ecos.sourceware.org/ml/systemtap/2010-q3/msg00145.html
76 #define __USDT_H
82 * -----
83 * - Initial release
85 #define USDT_MAJOR_VERSION 0
86 #define USDT_MINOR_VERSION 1
87 #define USDT_PATCH_VERSION 0
89 /* C++20 and C23 added __VA_OPT__ as a standard replacement for non-standard `##__VA_ARGS__` extens…
91 #define __usdt_va_opt 1
92 #define __usdt_va_args(...) __VA_OPT__(,) __VA_ARGS__
94 #define __usdt_va_args(...) , ##__VA_ARGS__
98 * Trigger USDT with `group`:`name` identifier and pass through `args` as its
109 #define USDT(group, name, ...) \ argument
110 __usdt_probe(group, name, __usdt_sema_none, 0 __VA_OPT__(,) __VA_ARGS__)
112 #define USDT(group, name, ...) \ argument
113 __usdt_probe(group, name, __usdt_sema_none, 0, ##__VA_ARGS__)
117 * Trigger USDT with `group`:`name` identifier and pass through `args` as its
119 * implicitly-defined associated USDT semaphore, which will be "activated" by
129 * prepare USDT arguments. Use USDT_IS_ACTIVE(group, name) to check whether
141 * them. I.e., if you use USDT_WITH_SEMA() with the same USDT group and name
143 * conflict, per se, but will define independent USDT semaphores, one for each
144 * shared library/executable in which USDT_WITH_SEMA(group, name) is used.
148 * activated USDT semaphore. In short, it's best to use unique USDT group:name
156 #define USDT_WITH_SEMA(group, name, ...) \ argument
157 __usdt_probe(group, name, \
158 __usdt_sema_implicit, __usdt_sema_name(group, name) \
161 #define USDT_WITH_SEMA(group, name, ...) \ argument
162 __usdt_probe(group, name, \
163 __usdt_sema_implicit, __usdt_sema_name(group, name), \
170 * Check if USDT with `group`:`name` identifier is "active" (i.e., whether it
176 * USDT_WITH_SEMA() macro which will implicitly define associated USDT
183 * case should result in one-time wasted extra data collection and processing.
185 #define USDT_IS_ACTIVE(group, name) ({ \ argument
186 extern struct usdt_sema __usdt_sema_name(group, name) \
187 __usdt_asm_name(__usdt_sema_name(group, name)); \
188 __usdt_sema_implicit(__usdt_sema_name(group, name)); \
189 __usdt_sema_name(group, name).active > 0; \
193 * APIs for working with user-defined explicit USDT semaphores.
207 * Underlying C global variable name for user-defined USDT semaphore with
211 #define USDT_SEMA(sema) __usdt_sema_##sema
214 * Define storage for user-defined USDT semaphore `sema`.
216 * Should be used only once in non-header source file to let compiler allocate
221 * one definition of user-defined USDT semaphore with given `sema` identifier,
225 * For C++, it is allowed to use USDT_DEFINE_SEMA() both in global namespace
228 * referenced, or any of its parent namespaces, so the C++ language-level
231 * (they have a corresponding `__usdt_sema_<name>` symbol, which can be linked
232 * against from C or C++ code, if necessary). To keep it simple, putting
234 * no-brainer solution. All these aspects are irrelevant for plain C, because
235 * C doesn't have namespaces and everything is always in the global namespace.
237 * N.B. Due to USDT metadata being recorded in non-allocatable ELF note
242 * library or executable to avoid unpleasant surprises with half-working USDT
247 #define USDT_DEFINE_SEMA(sema) \
253 * Declare extern reference to user-defined USDT semaphore `sema`.
257 * multiple compilation units (i.e., .c and .cpp files).
259 * See USDT_DEFINE_SEMA() notes above for C++ language usage peculiarities.
261 #define USDT_DECLARE_SEMA(sema) \
265 * Check if user-defined USDT semaphore `sema` is "active" (i.e., whether it
275 * in one-time missed USDT event or wasted extra data collection and
276 * processing. USDT-using tracers should be written with this in mind and is
279 #define USDT_SEMA_IS_ACTIVE(sema) (USDT_SEMA(sema).active > 0)
282 * Invoke USDT specified by `group` and `name` identifiers and associate
283 * explicitly user-defined semaphore `sema` with it. Pass through `args` as
290 #define USDT_WITH_EXPLICIT_SEMA(sema, group, name, ...) \ argument
291 __usdt_probe(group, name, __usdt_sema_explicit, USDT_SEMA(sema), ##__VA_ARGS__)
293 #define USDT_WITH_EXPLICIT_SEMA(sema, group, name, ...) \ argument
294 __usdt_probe(group, name, __usdt_sema_explicit, USDT_SEMA(sema) __VA_OPT__(,) __VA_ARGS__)
302 #define USDT_ARG_CONSTRAINT nZr
304 #define USDT_ARG_CONSTRAINT g
306 #define USDT_ARG_CONSTRAINT nmr
308 #define USDT_ARG_CONSTRAINT nor
314 #define USDT_NOP nop 0
316 #define USDT_NOP nop
323 /* USDT name for implicitly-defined USDT semaphore, derived from group:name */
324 #define __usdt_sema_name(group, name) __usdt_sema_##group##__##name argument
326 #define __usdt_sema_sec __attribute__((section(".probes")))
328 #define __usdt_concat(a, b) a ## b
329 #define __usdt_apply(fn, n) __usdt_concat(fn, n)
332 #define __usdt_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
337 #define __usdt_narg(...) __usdt_nth(_ __VA_OPT__(,) __VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2…
339 #define __usdt_narg(...) __usdt_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
343 #define __usdt_hash #
344 #define __usdt_str_(x) #x
345 #define __usdt_str(x) __usdt_str_(x)
348 #define __usdt_asm_name(name) __asm__(__usdt_str(name)) argument
351 #define __usdt_asm0() "\n"
352 #define __usdt_asm1(x) __usdt_str(x) "\n"
353 #define __usdt_asm2(x, ...) __usdt_str(x) "," __usdt_asm1(__VA_ARGS__)
354 #define __usdt_asm3(x, ...) __usdt_str(x) "," __usdt_asm2(__VA_ARGS__)
355 #define __usdt_asm4(x, ...) __usdt_str(x) "," __usdt_asm3(__VA_ARGS__)
356 #define __usdt_asm5(x, ...) __usdt_str(x) "," __usdt_asm4(__VA_ARGS__)
357 #define __usdt_asm6(x, ...) __usdt_str(x) "," __usdt_asm5(__VA_ARGS__)
358 #define __usdt_asm7(x, ...) __usdt_str(x) "," __usdt_asm6(__VA_ARGS__)
359 #define __usdt_asm8(x, ...) __usdt_str(x) "," __usdt_asm7(__VA_ARGS__)
360 #define __usdt_asm9(x, ...) __usdt_str(x) "," __usdt_asm8(__VA_ARGS__)
361 #define __usdt_asm10(x, ...) __usdt_str(x) "," __usdt_asm9(__VA_ARGS__)
362 #define __usdt_asm11(x, ...) __usdt_str(x) "," __usdt_asm10(__VA_ARGS__)
363 #define __usdt_asm12(x, ...) __usdt_str(x) "," __usdt_asm11(__VA_ARGS__)
364 #define __usdt_asm(...) __usdt_apply(__usdt_asm, __usdt_narg(__VA_ARGS__))(__VA_ARGS__)
367 #define __usdt_asm_addr .8byte
369 #define __usdt_asm_addr .4byte
372 #define __usdt_asm_strz_(x) __usdt_asm1(.asciz #x)
373 #define __usdt_asm_strz(x) __usdt_asm_strz_(x)
374 #define __usdt_asm_str_(x) __usdt_asm1(.ascii #x)
375 #define __usdt_asm_str(x) __usdt_asm_str_(x)
379 #define __usdt_sema_none(sema)
384 #define __usdt_sema_implicit(sema) \
402 #define __usdt_sema_explicit(sema) \
407 #define __usdt_probe(group, name, sema_def, sema, ...) do { \ argument
413 __usdt_asm3( .4byte 992f-991f,994f-993f,3) \
420 __usdt_asm_strz(name) \
444 * i386, 64-bit value may be put in register pairs, and a register
445 * name stored would identify just one of them. Previously, gcc was
446 * asked to emit the %w[id] (16-bit alias of some registers holding
447 * operands), even when a wider 32-bit value was used.
449 * Bottom line: the byte-width given before the @ sign governs. If
452 * architecture-specific heuristics to figure out where the compiler
456 #define __usdt_argref(id) %I[id]%[id]
458 #define __usdt_argref(id) %k[id] /* gcc.gnu.org/PR80115 sourceware.org/PR24541 */
460 #define __usdt_argref(id) %[id]
463 #define __usdt_asm_arg(n) __usdt_asm_str(%c[__usdt_asz##n]) \
467 #define __usdt_asm_args0 /* no arguments */
468 #define __usdt_asm_args1 __usdt_asm_arg(1)
469 #define __usdt_asm_args2 __usdt_asm_args1 __usdt_asm1(.ascii " ") __usdt_asm_arg(2)
470 #define __usdt_asm_args3 __usdt_asm_args2 __usdt_asm1(.ascii " ") __usdt_asm_arg(3)
471 #define __usdt_asm_args4 __usdt_asm_args3 __usdt_asm1(.ascii " ") __usdt_asm_arg(4)
472 #define __usdt_asm_args5 __usdt_asm_args4 __usdt_asm1(.ascii " ") __usdt_asm_arg(5)
473 #define __usdt_asm_args6 __usdt_asm_args5 __usdt_asm1(.ascii " ") __usdt_asm_arg(6)
474 #define __usdt_asm_args7 __usdt_asm_args6 __usdt_asm1(.ascii " ") __usdt_asm_arg(7)
475 #define __usdt_asm_args8 __usdt_asm_args7 __usdt_asm1(.ascii " ") __usdt_asm_arg(8)
476 #define __usdt_asm_args9 __usdt_asm_args8 __usdt_asm1(.ascii " ") __usdt_asm_arg(9)
477 #define __usdt_asm_args10 __usdt_asm_args9 __usdt_asm1(.ascii " ") __usdt_asm_arg(10)
478 #define __usdt_asm_args11 __usdt_asm_args10 __usdt_asm1(.ascii " ") __usdt_asm_arg(11)
479 #define __usdt_asm_args12 __usdt_asm_args11 __usdt_asm1(.ascii " ") __usdt_asm_arg(12)
480 #define __usdt_asm_args(...) __usdt_apply(__usdt_asm_args, __usdt_narg(__VA_ARGS__))
482 #define __usdt_is_arr(x) (__builtin_classify_type(x) == 14 || __builtin_classify_type(x) == 5)
483 #define __usdt_arg_size(x) (__usdt_is_arr(x) ? sizeof(void *) : sizeof(x))
486 * We can't use __builtin_choose_expr() in C++, so fall back to table-based
491 #define __usdt_is_signed(x) (!__usdt_is_arr(x) && __usdt_t<__typeof(x)>::is_signed)
499 #define __usdt_def_signed(T) \
504 #define __usdt_maybe_signed(T) \
505 template<> struct __usdt_t<T> { static const bool is_signed = (T)-1 < (T)1; }; \
506 template<> struct __usdt_t<const T> { static const bool is_signed = (T)-1 < (T)1; }; \
507 template<> struct __usdt_t<volatile T> { static const bool is_signed = (T)-1 < (T)1; }; \
508 template<> struct __usdt_t<const volatile T> { static const bool is_signed = (T)-1 < (T)1; }
520 #define __usdt_is_inttype(x) (__builtin_classify_type(x) >= 1 && __builtin_classify_type(x) <= 4)
521 #define __usdt_inttype(x) __typeof(__builtin_choose_expr(__usdt_is_inttype(x), (x), 0U))
522 #define __usdt_is_signed(x) ((__usdt_inttype(x))-1 < (__usdt_inttype(x))1)
526 #define __usdt_asm_op(n, x) \
527 [__usdt_asz##n] "n" ((__usdt_is_signed(x) ? (int)-1 : 1) * (int)__usdt_arg_size(x)), \
530 #define __usdt_asm_ops0() [__usdt_dummy] "g" (0)
531 #define __usdt_asm_ops1(x) __usdt_asm_op(1, x)
532 #define __usdt_asm_ops2(a,x) __usdt_asm_ops1(a), __usdt_asm_op(2, x)
533 #define __usdt_asm_ops3(a,b,x) __usdt_asm_ops2(a,b), __usdt_asm_op(3, x)
534 #define __usdt_asm_ops4(a,b,c,x) __usdt_asm_ops3(a,b,c), __usdt_asm_op(4, x)
535 #define __usdt_asm_ops5(a,b,c,d,x) __usdt_asm_ops4(a,b,c,d), __usdt_asm_op(5, x)
536 #define __usdt_asm_ops6(a,b,c,d,e,x) __usdt_asm_ops5(a,b,c,d,e), __usdt_asm_op(6, x)
537 #define __usdt_asm_ops7(a,b,c,d,e,f,x) __usdt_asm_ops6(a,b,c,d,e,f), __usdt_asm_op(7, x)
538 #define __usdt_asm_ops8(a,b,c,d,e,f,g,x) __usdt_asm_ops7(a,b,c,d,e,f,g), __usdt_asm_op(8, x)
539 #define __usdt_asm_ops9(a,b,c,d,e,f,g,h,x) __usdt_asm_ops8(a,b,c,d,e,f,g,h), __usdt_asm_op(9, x)
540 #define __usdt_asm_ops10(a,b,c,d,e,f,g,h,i,x) __usdt_asm_ops9(a,b,c,d,e,f,g,h,i), __usdt_asm_op(10…
541 #define __usdt_asm_ops11(a,b,c,d,e,f,g,h,i,j,x) __usdt_asm_ops10(a,b,c,d,e,f,g,h,i,j), __usdt_asm_…
542 #define __usdt_asm_ops12(a,b,c,d,e,f,g,h,i,j,k,x) __usdt_asm_ops11(a,b,c,d,e,f,g,h,i,j,k), __usdt_a…
543 #define __usdt_asm_ops(...) __usdt_apply(__usdt_asm_ops, __usdt_narg(__VA_ARGS__))(__VA_ARGS__)