diff --git a/libweston/perfetto/u_perfetto.cc b/libweston/perfetto/u_perfetto.cc index 9d0a2eb99..b7a96fd2a 100644 --- a/libweston/perfetto/u_perfetto.cc +++ b/libweston/perfetto/u_perfetto.cc @@ -151,6 +151,83 @@ util_perfetto_next_id(void) return p_atomic_inc_return(&util_perfetto_unique_id); } +static void +util_perfetto_flush_debug_annotation(perfetto::EventContext *ctx, + unsigned int nr_entries, + struct weston_debug_annotation *annots) +{ + if (nr_entries == 0) + return; + + for (unsigned int idx = 0; idx < nr_entries; idx++) { + switch (annots[idx].type) { + case WESTON_DEBUG_ANNOTATION_INT_VAL: + ctx->AddDebugAnnotation(annots[idx].key, annots[idx].ivalue); + break; + case WESTON_DEBUG_ANNOTATION_FLOAT_VAL: + ctx->AddDebugAnnotation(annots[idx].key, annots[idx].fvalue); + break; + case WESTON_DEBUG_ANNOTATION_STR_VAL: + ctx->AddDebugAnnotation(annots[idx].key, annots[idx].svalue); + break; + default: + break; + } + } + +} + +void +util_perfetto_trace_commit_debug_annots(uint64_t id, const char *name, + unsigned int nr_entries, + struct weston_debug_annotation *annots) +{ + if (id) { + TRACE_EVENT_INSTANT(UTIL_PERFETTO_CATEGORY_DEFAULT_STR, + nullptr, + perfetto::Flow::ProcessScoped(id), + [&](perfetto::EventContext ctx) { + ctx.event()->set_name(name); + util_perfetto_flush_debug_annotation(&ctx, nr_entries, annots); + }); + return; + } + + TRACE_EVENT_INSTANT(UTIL_PERFETTO_CATEGORY_DEFAULT_STR, + nullptr, + [&](perfetto::EventContext ctx) { + ctx.event()->set_name(name); + util_perfetto_flush_debug_annotation(&ctx, nr_entries, annots); + }); +} + +void +util_perfetto_trace_commit_annotate_func(const char *name, unsigned int nr_entries, + struct weston_debug_annotation *annots) +{ + TRACE_EVENT_BEGIN(UTIL_PERFETTO_CATEGORY_DEFAULT_STR, + nullptr, + [&](perfetto::EventContext ctx) { + ctx.event()->set_name(name); + util_perfetto_flush_debug_annotation(&ctx, nr_entries, annots); + }); +} + +void +util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, + unsigned int nr_entries, + struct weston_debug_annotation *annots) +{ + TRACE_EVENT_BEGIN(UTIL_PERFETTO_CATEGORY_DEFAULT_STR, + nullptr, + perfetto::Flow::ProcessScoped(id), + [&](perfetto::EventContext ctx) { + ctx.event()->set_name(name); + util_perfetto_flush_debug_annotation(&ctx, nr_entries, annots); + }); +} + + class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver { public: UtilPerfettoObserver() { perfetto::TrackEvent::AddSessionObserver(this); } diff --git a/libweston/perfetto/u_perfetto.h b/libweston/perfetto/u_perfetto.h index 576348fce..4c84b7250 100644 --- a/libweston/perfetto/u_perfetto.h +++ b/libweston/perfetto/u_perfetto.h @@ -39,6 +39,22 @@ extern "C" { #endif +enum weston_debug_annotation_type { + WESTON_DEBUG_ANNOTATION_INT_VAL, + WESTON_DEBUG_ANNOTATION_FLOAT_VAL, + WESTON_DEBUG_ANNOTATION_STR_VAL, +}; + +struct weston_debug_annotation { + const char *key; + enum weston_debug_annotation_type type; + union { + int ivalue; + float fvalue; + const char *svalue; + }; +}; + #ifdef HAVE_PERFETTO extern int util_perfetto_tracing_state; @@ -63,6 +79,15 @@ void util_perfetto_trace_full_begin(const char *name, uint64_t track_id, uint64_ void util_perfetto_trace_full_end(const char *name, uint64_t track_id, clockid_t clock, uint64_t timestamp); +void util_perfetto_trace_commit_debug_annots(uint64_t id, const char *name, + unsigned int entries, struct weston_debug_annotation *annots); + +void util_perfetto_trace_commit_annotate_func(const char *name, + unsigned int entries, struct weston_debug_annotation *annots); + +void util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, + unsigned int entries, struct weston_debug_annotation *annots); + uint64_t util_perfetto_next_id(void); uint64_t util_perfetto_new_track(const char *name); @@ -104,6 +129,27 @@ util_perfetto_trace_full_end(const char *name, uint64_t track_id, clockid_t cloc { } +static inline void +util_perfetto_trace_commit_debug_annots(uint64_t id, const char *name, + unsigned int entries, + struct weston_debug_annotation *annots) +{ +} + +static inline void +util_perfetto_trace_commit_annotate_func(const char *name, + unsigned int entries, + struct weston_debug_annotation *annots) +{ +} + +static inline void +util_perfetto_trace_commit_annotate_func_flow(uint64_t id, const char *name, + unsigned int entries, + struct weston_debug_annotation *annots) +{ +} + static inline void util_perfetto_counter_set(const char *name, double value) { } diff --git a/libweston/weston-trace.h b/libweston/weston-trace.h index 154663157..b2ba55492 100644 --- a/libweston/weston-trace.h +++ b/libweston/weston-trace.h @@ -11,6 +11,7 @@ #define WESTON_TRACE_H #include "perfetto/u_perfetto.h" +#include #if defined(HAVE_PERFETTO) @@ -28,6 +29,9 @@ # endif #endif +/* maximum allowed debug annotations */ +#define WESTON_MAX_DEBUG_ANNOTS 128 + /* note that util_perfetto_is_tracing_enabled always returns false until * util_perfetto_init is called */ @@ -69,6 +73,53 @@ clock, timestamp); \ } while (0) +#define _WESTON_TRACE_BEGIN_ANNOTATION() \ + struct weston_debug_annotation __pd_annots[WESTON_MAX_DEBUG_ANNOTS]; \ + unsigned int __pd_i = 0 + +#define _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) \ + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ + __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_INT_VAL; \ + __pd_annots[__pd_i].ivalue = v; \ + __pd_annots[__pd_i].key = k; \ + __pd_i++ + +#define _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) \ + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ + __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_FLOAT_VAL; \ + __pd_annots[__pd_i].fvalue = v; \ + __pd_annots[__pd_i].key = k; \ + __pd_i++ + +#define _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) \ + weston_assert_u32_gt(NULL, WESTON_MAX_DEBUG_ANNOTS, __pd_i); \ + __pd_annots[__pd_i].type = WESTON_DEBUG_ANNOTATION_STR_VAL; \ + __pd_annots[__pd_i].svalue = v; \ + __pd_annots[__pd_i].key = k; \ + __pd_i++ + +#define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) \ + do { \ + if (unlikely(util_perfetto_is_tracing_enabled())) { \ + _weston_trace_scope_annotate_commit(id, name, &__pd_i, __pd_annots); \ + } \ + } while (0) + +/* annotated funcs */ +#define _WESTON_TRACE_ANNOTATE_FUNC_BEGIN(name, nr_entries, annots) \ + do { \ + if (unlikely(util_perfetto_is_tracing_enabled())) { \ + util_perfetto_trace_commit_annotate_func(name, *nr_entries, annots); \ + } \ + } while (0) + +#define _WESTON_TRACE_ANNOTATE_FUNC_BEGIN_FLOW(name, id, nr_entries, annots) \ + do { \ + if (unlikely(util_perfetto_is_tracing_enabled())) { \ + util_perfetto_trace_commit_annotate_func_flow(id, name, *nr_entries, annots); \ + } \ + } while (0) + #if __has_attribute(cleanup) && __has_attribute(unused) #define _WESTON_TRACE_SCOPE_VAR_CONCAT(name, suffix) name##suffix @@ -92,6 +143,16 @@ __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ _weston_trace_scope_flow_begin(name, id) +#define _WESTON_TRACE_ANNOTATE_FUNC(name) \ + int _WESTON_TRACE_SCOPE_VAR(__LINE__) \ + __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ + _weston_trace_annotate_func_begin(name, &__pd_i, __pd_annots) + +#define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) \ + int _WESTON_TRACE_SCOPE_VAR(__LINE__) \ + __attribute__((cleanup(_weston_trace_scope_end), unused)) = \ + _weston_trace_annotate_func_begin_flow(name, id, &__pd_i, __pd_annots) + static inline int _weston_trace_scope_begin(const char *name) { @@ -108,6 +169,53 @@ _weston_trace_scope_flow_begin(const char *name, uint64_t *id) return 0; } +static inline void +_weston_trace_scope_annotate_commit(uint64_t *id, const char *name, + unsigned int *nr_entries, + struct weston_debug_annotation *annots) +{ + if (id && *id == 0) { + *id = util_perfetto_next_id(); + util_perfetto_trace_commit_debug_annots(*id, name, *nr_entries, annots); + goto reset_entries; + } + + util_perfetto_trace_commit_debug_annots(0, name, *nr_entries, annots); + + /* reset the array and counter */ +reset_entries: + memset(annots, 0, sizeof(struct weston_debug_annotation) * *nr_entries); + *nr_entries = 0; +} + +static inline int +_weston_trace_annotate_func_begin(const char *name, unsigned int *nr_entries, + struct weston_debug_annotation *annots) +{ + _WESTON_TRACE_ANNOTATE_FUNC_BEGIN(name, nr_entries, annots); + + /* reset the array and counter */ + memset(annots, 0, sizeof(struct weston_debug_annotation) * *nr_entries); + *nr_entries = 0; + return 0; +} + +static inline int +_weston_trace_annotate_func_begin_flow(const char *name, uint64_t *id, + unsigned int *nr_entries, + struct weston_debug_annotation *annots) +{ + if (*id == 0) + *id = util_perfetto_next_id(); + + _WESTON_TRACE_ANNOTATE_FUNC_BEGIN_FLOW(name, *id, nr_entries, annots); + + /* reset the array and counter */ + memset(annots, 0, sizeof(struct weston_debug_annotation) * *nr_entries); + *nr_entries = 0; + return 0; +} + static inline void _weston_trace_scope_end(int *scope) { @@ -130,6 +238,14 @@ _weston_trace_scope_end(int *scope) #define _WESTON_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, clock, timestamp) #define _WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp) +#define _WESTON_TRACE_BEGIN_ANNOTATION() +#define _WESTON_TRACE_COMMIT_ANNOTATION(id, name) +#define _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) +#define _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) +#define _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) +#define _WESTON_TRACE_ANNOTATE_FUNC() +#define _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, name) + #endif /* HAVE_PERFETTO */ #define WESTON_TRACE_SCOPE(name) _WESTON_TRACE_SCOPE(name) @@ -142,4 +258,25 @@ _weston_trace_scope_end(int *scope) #define WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp) \ _WESTON_TRACE_TIMESTAMP_END(name, track_id, clock, timestamp) +#define WESTON_TRACE_BEGIN_ANNOTATION() \ + _WESTON_TRACE_BEGIN_ANNOTATION() + +#define WESTON_TRACE_ANNOTATE_ADD_INT(k, v) \ + _WESTON_TRACE_ANNOTATE_ADD_INT(k, v) + +#define WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) \ + _WESTON_TRACE_ANNOTATE_ADD_FLOAT(k, v) + +#define WESTON_TRACE_ANNOTATE_ADD_STR(k, v) \ + _WESTON_TRACE_ANNOTATE_ADD_STR(k, v) + +#define WESTON_TRACE_COMMIT_ANNOTATION(id) \ + _WESTON_TRACE_COMMIT_ANNOTATION(id, __func__) + +#define WESTON_TRACE_ANNOTATE_FUNC() \ + _WESTON_TRACE_ANNOTATE_FUNC(__func__) + +#define WESTON_TRACE_ANNOTATE_FUNC_FLOW(id) \ + _WESTON_TRACE_ANNOTATE_FUNC_FLOW(id, __func__) + #endif /* WESTON_TRACE_H */