Module: Mesa Branch: main Commit: 54b105f75d39203b70607b5e494d25cc322a0461 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=54b105f75d39203b70607b5e494d25cc322a0461
Author: Chia-I Wu <[email protected]> Date: Sun May 16 21:29:49 2021 -0700 util/perfetto: add a simple C wrapper for track events The C wrapper only uses public APIs from the C++ SDK. For efficient tracepoint skipping, it copies the states of categories (there is one category in this commit) to a util_perfetto_category_states array. Other options are to use percetto, or wait for an official C SDK. Signed-off-by: Chia-I Wu <[email protected]> Acked-by: Rob Clark <[email protected]> Reviewed-by: Antonio Caggiano <[email protected]> Reviewed-by: Yiwei Zhang <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18260> --- src/util/perf/u_perfetto.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++- src/util/perf/u_perfetto.h | 54 +++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/src/util/perf/u_perfetto.cc b/src/util/perf/u_perfetto.cc index 5158c9442e9..10facb38645 100644 --- a/src/util/perf/u_perfetto.cc +++ b/src/util/perf/u_perfetto.cc @@ -21,11 +21,93 @@ * SOFTWARE. */ +#include "u_perfetto.h" + #include <perfetto.h> #include "c11/threads.h" +#include "util/macros.h" -#include "u_perfetto.h" +/* perfetto requires string literals */ +#define UTIL_PERFETTO_CATEGORY_DEFAULT_STR "mesa.default" +#define UTIL_PERFETTO_CATEGORY_SLOW_STR "mesa.slow" + +PERFETTO_DEFINE_CATEGORIES( + perfetto::Category(UTIL_PERFETTO_CATEGORY_DEFAULT_STR) + .SetDescription("Mesa default events"), + perfetto::Category(UTIL_PERFETTO_CATEGORY_SLOW_STR) + .SetDescription("Mesa slow events") + .SetTags("slow")); + +PERFETTO_TRACK_EVENT_STATIC_STORAGE(); + +int util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_COUNT]; + +static void +util_perfetto_update_category_states(void) +{ +#define UPDATE_CATEGORY(cat) \ + p_atomic_set( \ + &util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_##cat], \ + TRACE_EVENT_CATEGORY_ENABLED(UTIL_PERFETTO_CATEGORY_##cat##_STR)) + UPDATE_CATEGORY(DEFAULT); + UPDATE_CATEGORY(SLOW); +#undef UPDATE_CATEGORY +} + +void +util_perfetto_trace_begin(enum util_perfetto_category category, + const char *name) +{ +#define TRACE_BEGIN(cat, name) \ + TRACE_EVENT_BEGIN( \ + UTIL_PERFETTO_CATEGORY_##cat##_STR, nullptr, \ + [&](perfetto::EventContext ctx) { ctx.event()->set_name(name); }) + switch (category) { + case UTIL_PERFETTO_CATEGORY_DEFAULT: + TRACE_BEGIN(DEFAULT, name); + break; + case UTIL_PERFETTO_CATEGORY_SLOW: + TRACE_BEGIN(SLOW, name); + break; + default: + unreachable("bad perfetto category"); + } +#undef TRACE_BEGIN +} + +void +util_perfetto_trace_end(enum util_perfetto_category category) +{ +#define TRACE_END(cat) TRACE_EVENT_END(UTIL_PERFETTO_CATEGORY_##cat##_STR) + switch (category) { + case UTIL_PERFETTO_CATEGORY_DEFAULT: + TRACE_END(DEFAULT); + break; + case UTIL_PERFETTO_CATEGORY_SLOW: + TRACE_END(SLOW); + break; + default: + unreachable("bad perfetto category"); + } +#undef TRACE_END + + util_perfetto_update_category_states(); +} + +class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver { + public: + UtilPerfettoObserver() { perfetto::TrackEvent::AddSessionObserver(this); } + + void OnStart(const perfetto::DataSourceBase::StartArgs &) override + { + util_perfetto_update_category_states(); + } + + /* XXX There is no PostStop callback. We have to call + * util_perfetto_update_category_states occasionally to poll. + */ +}; static void util_perfetto_fini(void) @@ -40,6 +122,10 @@ util_perfetto_init_once(void) perfetto::TracingInitArgs args; args.backends = perfetto::kSystemBackend; perfetto::Tracing::Initialize(args); + + static UtilPerfettoObserver observer; + perfetto::TrackEvent::Register(); + atexit(&util_perfetto_fini); } diff --git a/src/util/perf/u_perfetto.h b/src/util/perf/u_perfetto.h index a50f010b58f..fe8e88c3bd9 100644 --- a/src/util/perf/u_perfetto.h +++ b/src/util/perf/u_perfetto.h @@ -24,12 +24,64 @@ #ifndef _UTIL_PERFETTO_H #define _UTIL_PERFETTO_H +#include "util/u_atomic.h" #ifdef __cplusplus extern "C" { #endif -void util_perfetto_init(void); +enum util_perfetto_category { + UTIL_PERFETTO_CATEGORY_DEFAULT, + UTIL_PERFETTO_CATEGORY_SLOW, + + UTIL_PERFETTO_CATEGORY_COUNT, +}; + +#ifdef HAVE_PERFETTO + +extern int util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_COUNT]; + +void +util_perfetto_init(void); + +static inline bool +util_perfetto_is_category_enabled(enum util_perfetto_category category) +{ + return p_atomic_read_relaxed(&util_perfetto_category_states[category]); +} + +void +util_perfetto_trace_begin(enum util_perfetto_category category, + const char *name); + +void +util_perfetto_trace_end(enum util_perfetto_category category); + +#else /* HAVE_PERFETTO */ + +static inline void +util_perfetto_init(void) +{ +} + +static inline bool +util_perfetto_is_category_enabled(enum util_perfetto_category category) +{ + return false; +} + +static inline void +util_perfetto_trace_begin(enum util_perfetto_category category, + const char *name) +{ +} + +static inline void +util_perfetto_trace_end(enum util_perfetto_category category) +{ +} + +#endif /* HAVE_PERFETTO */ #ifdef __cplusplus }
