1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "perfetto/public/abi/tracing_session_abi.h"
18
19 #include <condition_variable>
20 #include <mutex>
21
22 #include "perfetto/tracing/tracing.h"
23 #include "protos/perfetto/config/trace_config.gen.h"
24
PerfettoTracingSessionSystemCreate()25 struct PerfettoTracingSessionImpl* PerfettoTracingSessionSystemCreate() {
26 std::unique_ptr<perfetto::TracingSession> tracing_session =
27 perfetto::Tracing::NewTrace(perfetto::kSystemBackend);
28 return reinterpret_cast<struct PerfettoTracingSessionImpl*>(
29 tracing_session.release());
30 }
31
PerfettoTracingSessionInProcessCreate()32 struct PerfettoTracingSessionImpl* PerfettoTracingSessionInProcessCreate() {
33 std::unique_ptr<perfetto::TracingSession> tracing_session =
34 perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
35 return reinterpret_cast<struct PerfettoTracingSessionImpl*>(
36 tracing_session.release());
37 }
38
PerfettoTracingSessionSetup(struct PerfettoTracingSessionImpl * session,void * cfg_begin,size_t cfg_len)39 void PerfettoTracingSessionSetup(struct PerfettoTracingSessionImpl* session,
40 void* cfg_begin,
41 size_t cfg_len) {
42 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
43 perfetto::TraceConfig cfg;
44 cfg.ParseFromArray(cfg_begin, cfg_len);
45 ts->Setup(cfg);
46 }
47
PerfettoTracingSessionSetStopCb(struct PerfettoTracingSessionImpl * session,PerfettoTracingSessionStopCb cb,void * user_arg)48 void PerfettoTracingSessionSetStopCb(struct PerfettoTracingSessionImpl* session,
49 PerfettoTracingSessionStopCb cb,
50 void* user_arg) {
51 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
52 ts->SetOnStopCallback([session, cb, user_arg]() { cb(session, user_arg); });
53 }
54
PerfettoTracingSessionStartAsync(struct PerfettoTracingSessionImpl * session)55 void PerfettoTracingSessionStartAsync(
56 struct PerfettoTracingSessionImpl* session) {
57 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
58 ts->Start();
59 }
60
PerfettoTracingSessionStartBlocking(struct PerfettoTracingSessionImpl * session)61 void PerfettoTracingSessionStartBlocking(
62 struct PerfettoTracingSessionImpl* session) {
63 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
64 ts->StartBlocking();
65 }
66
PerfettoTracingSessionFlushAsync(struct PerfettoTracingSessionImpl * session,uint32_t timeout_ms,PerfettoTracingSessionFlushCb cb,void * user_arg)67 void PerfettoTracingSessionFlushAsync(
68 struct PerfettoTracingSessionImpl* session,
69 uint32_t timeout_ms,
70 PerfettoTracingSessionFlushCb cb,
71 void* user_arg) {
72 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
73 std::function<void(bool)> flush_cb = [](bool) {};
74 if (cb) {
75 flush_cb = [cb, session, user_arg](bool success) {
76 cb(session, success, user_arg);
77 };
78 }
79 ts->Flush(std::move(flush_cb), timeout_ms);
80 }
81
PerfettoTracingSessionFlushBlocking(struct PerfettoTracingSessionImpl * session,uint32_t timeout_ms)82 bool PerfettoTracingSessionFlushBlocking(
83 struct PerfettoTracingSessionImpl* session,
84 uint32_t timeout_ms) {
85 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
86 return ts->FlushBlocking(timeout_ms);
87 }
88
PerfettoTracingSessionStopAsync(struct PerfettoTracingSessionImpl * session)89 void PerfettoTracingSessionStopAsync(
90 struct PerfettoTracingSessionImpl* session) {
91 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
92 ts->Stop();
93 }
94
PerfettoTracingSessionStopBlocking(struct PerfettoTracingSessionImpl * session)95 void PerfettoTracingSessionStopBlocking(
96 struct PerfettoTracingSessionImpl* session) {
97 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
98 ts->StopBlocking();
99 }
100
PerfettoTracingSessionReadTraceBlocking(struct PerfettoTracingSessionImpl * session,PerfettoTracingSessionReadCb callback,void * user_arg)101 void PerfettoTracingSessionReadTraceBlocking(
102 struct PerfettoTracingSessionImpl* session,
103 PerfettoTracingSessionReadCb callback,
104 void* user_arg) {
105 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
106
107 std::mutex mutex;
108 std::condition_variable cv;
109
110 bool all_read = false;
111
112 ts->ReadTrace([&mutex, &all_read, &cv, session, callback, user_arg](
113 perfetto::TracingSession::ReadTraceCallbackArgs args) {
114 callback(session, static_cast<const void*>(args.data), args.size,
115 args.has_more, user_arg);
116 std::unique_lock<std::mutex> lock(mutex);
117 all_read = !args.has_more;
118 if (all_read)
119 cv.notify_one();
120 });
121
122 {
123 std::unique_lock<std::mutex> lock(mutex);
124 cv.wait(lock, [&all_read] { return all_read; });
125 }
126 }
127
PerfettoTracingSessionDestroy(struct PerfettoTracingSessionImpl * session)128 void PerfettoTracingSessionDestroy(struct PerfettoTracingSessionImpl* session) {
129 auto* ts = reinterpret_cast<perfetto::TracingSession*>(session);
130 delete ts;
131 }
132