Repository: bitcoin/bitcoin
File: src/util/trace.h (C/C++)

Code before:
// Copyright (c) 2020-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_TRACE_H
#define BITCOIN_UTIL_TRACE_H

#include <bitcoin-build-config.h> // IWYU pragma: keep

#ifdef ENABLE_TRACING

#include <sys/sdt.h>

#define TRACE(context, event) DTRACE_PROBE(context, event)
#define TRACE1(context, event, a) DTRACE_PROBE1(context, event, a)
#define TRACE2(context, event, a, b) DTRACE_PROBE2(context, event, a, b)
#define TRACE3(context, event, a, b, c) DTRACE_PROBE3(context, event, a, b, c)
#define TRACE4(context, event, a, b, c, d) DTRACE_PROBE4(context, event, a, b, c, d)
#define TRACE5(context, event, a, b, c, d, e) DTRACE_PROBE5(context, event, a, b, c, d, e)
#define TRACE6(context, event, a, b, c, d, e, f) DTRACE_PROBE6(context, event, a, b, c, d, e, f)
#define TRACE7(context, event, a, b, c, d, e, f, g) DTRACE_PROBE7(context, event, a, b, c, d, e, f, g)
#define TRACE8(context, event, a, b, c, d, e, f, g, h) DTRACE_PROBE8(context, event, a, b, c, d, e, f, g, h)
#define TRACE9(context, event, a, b, c, d, e, f, g, h, i) DTRACE_PROBE9(context, event, a, b, c, d, e, f, g, h, i)
#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j) DTRACE_PROBE10(context, event, a, b, c, d, e, f, g, h, i, j)
#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k) DTRACE_PROBE11(context, event, a, b, c, d, e, f, g, h, i, j, k)
#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l) DTRACE_PROBE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l)

#else

#define TRACE(context, event)
#define TRACE1(context, event, a)
#define TRACE2(context, event, a, b)
#define TRACE3(context, event, a, b, c)
#define TRACE4(context, event, a, b, c, d)
#define TRACE5(context, event, a, b, c, d, e)
#define TRACE6(context, event, a, b, c, d, e, f)
#define TRACE7(context, event, a, b, c, d, e, f, g)
#define TRACE8(context, event, a, b, c, d, e, f, g, h)
#define TRACE9(context, event, a, b, c, d, e, f, g, h, i)
#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j)
#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k)
#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l)

#endif


#endif // BITCOIN_UTIL_TRACE_H


Review comment (performance):
Thinking about it: We might not need an extra `TRACEPOINT_UNCHECKED` macro. We can also use the `TRACEPOINT` in all places where we'd use the unchecked one. This would mean would do two `TRACEPOINT_ACTIVE` checks, but these are extremely cheap and might even be optimized to one by the compiler. 

Dropping the unchecked version results in is a smaller, better internal tracepoint API and removes the possibility that someone uses the unchecked version but doesn't gate it.

Code after:
// to be a global variable. It's placed in the '.probes' ELF section.
#define TRACEPOINT_SEMAPHORE(context, event) \
    unsigned short context##_##event##_semaphore __attribute__((section(".probes")))

#include <sys/sdt.h>

// Returns true if something is attached to the tracepoint.
#define TRACEPOINT_ACTIVE(context, event) (context##_##event##_semaphore > 0)

// A USDT tracepoint with one to twelve arguments. It's checked that the
// tracepoint is active before preparing its arguments.
#define TRACEPOINT(context, event, ...)                                         \
    do {                                                                        \
        if (TRACEPOINT_ACTIVE(context, event)) {                                \
            STAP_PROBEV(context, event __VA_OPT__(, ) __VA_ARGS__);             \
        }                                                                       \
    } while(0)

#else

#define TRACEPOINT_SEMAPHORE(context, event)
#define TRACEPOINT_ACTIVE(context, event) false
#define TRACEPOINT(context, ...)

#endif // ENABLE_TRACING


#endif // BITCOIN_UTIL_TRACE_H