1 /*
2 * Copyright © 2021 Google, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "u_perfetto.h"
25
26 #include <perfetto.h>
27
28 #include "c11/threads.h"
29 #include "util/macros.h"
30
31 /* perfetto requires string literals */
32 #define UTIL_PERFETTO_CATEGORY_DEFAULT_STR "mesa.default"
33
34 PERFETTO_DEFINE_CATEGORIES(
35 perfetto::Category(UTIL_PERFETTO_CATEGORY_DEFAULT_STR)
36 .SetDescription("Mesa default events"));
37
38 PERFETTO_TRACK_EVENT_STATIC_STORAGE();
39
40 int util_perfetto_tracing_state;
41
42 static void
util_perfetto_update_tracing_state(void)43 util_perfetto_update_tracing_state(void)
44 {
45 p_atomic_set(&util_perfetto_tracing_state,
46 TRACE_EVENT_CATEGORY_ENABLED(UTIL_PERFETTO_CATEGORY_DEFAULT_STR));
47 }
48
49 void
util_perfetto_trace_begin(const char * name)50 util_perfetto_trace_begin(const char *name)
51 {
52 TRACE_EVENT_BEGIN(
53 UTIL_PERFETTO_CATEGORY_DEFAULT_STR, nullptr,
54 [&](perfetto::EventContext ctx) { ctx.event()->set_name(name); });
55 }
56
57 void
util_perfetto_trace_end(void)58 util_perfetto_trace_end(void)
59 {
60 TRACE_EVENT_END(UTIL_PERFETTO_CATEGORY_DEFAULT_STR);
61
62 util_perfetto_update_tracing_state();
63 }
64
65 class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver {
66 public:
UtilPerfettoObserver()67 UtilPerfettoObserver() { perfetto::TrackEvent::AddSessionObserver(this); }
68
OnStart(const perfetto::DataSourceBase::StartArgs &)69 void OnStart(const perfetto::DataSourceBase::StartArgs &) override
70 {
71 util_perfetto_update_tracing_state();
72 }
73
74 /* XXX There is no PostStop callback. We have to call
75 * util_perfetto_update_tracing_state occasionally to poll.
76 */
77 };
78
79 static void
util_perfetto_fini(void)80 util_perfetto_fini(void)
81 {
82 perfetto::Tracing::Shutdown();
83 }
84
85 static void
util_perfetto_init_once(void)86 util_perfetto_init_once(void)
87 {
88 // Connects to the system tracing service
89 perfetto::TracingInitArgs args;
90 args.backends = perfetto::kSystemBackend;
91 perfetto::Tracing::Initialize(args);
92
93 static UtilPerfettoObserver observer;
94 perfetto::TrackEvent::Register();
95
96 atexit(&util_perfetto_fini);
97 }
98
99 static once_flag perfetto_once_flag = ONCE_FLAG_INIT;
100
101 void
util_perfetto_init(void)102 util_perfetto_init(void)
103 {
104 call_once(&perfetto_once_flag, util_perfetto_init_once);
105 }
106