1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/tracing.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <atomic>
20*6dbdd20aSAndroid Build Coastguard Worker #include <condition_variable>
21*6dbdd20aSAndroid Build Coastguard Worker #include <mutex>
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/no_destructor.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/waitable_event.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/internal/track_event_internal.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "src/tracing/internal/tracing_muxer_impl.h"
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
30*6dbdd20aSAndroid Build Coastguard Worker namespace {
31*6dbdd20aSAndroid Build Coastguard Worker bool g_was_initialized = false;
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker // Wrapped in a function to avoid global constructor
InitializedMutex()34*6dbdd20aSAndroid Build Coastguard Worker std::mutex& InitializedMutex() {
35*6dbdd20aSAndroid Build Coastguard Worker static base::NoDestructor<std::mutex> initialized_mutex;
36*6dbdd20aSAndroid Build Coastguard Worker return initialized_mutex.ref();
37*6dbdd20aSAndroid Build Coastguard Worker }
38*6dbdd20aSAndroid Build Coastguard Worker } // namespace
39*6dbdd20aSAndroid Build Coastguard Worker
40*6dbdd20aSAndroid Build Coastguard Worker // static
InitializeInternal(const TracingInitArgs & args)41*6dbdd20aSAndroid Build Coastguard Worker void Tracing::InitializeInternal(const TracingInitArgs& args) {
42*6dbdd20aSAndroid Build Coastguard Worker base::InitializeTime();
43*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(InitializedMutex());
44*6dbdd20aSAndroid Build Coastguard Worker // If it's the first time Initialize is called, set some global params.
45*6dbdd20aSAndroid Build Coastguard Worker if (!g_was_initialized) {
46*6dbdd20aSAndroid Build Coastguard Worker // Make sure the headers and implementation files agree on the build config.
47*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(args.dcheck_is_on_ == PERFETTO_DCHECK_IS_ON());
48*6dbdd20aSAndroid Build Coastguard Worker if (args.log_message_callback) {
49*6dbdd20aSAndroid Build Coastguard Worker base::SetLogMessageCallback(args.log_message_callback);
50*6dbdd20aSAndroid Build Coastguard Worker }
51*6dbdd20aSAndroid Build Coastguard Worker
52*6dbdd20aSAndroid Build Coastguard Worker if (args.use_monotonic_clock) {
53*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(!args.use_monotonic_raw_clock);
54*6dbdd20aSAndroid Build Coastguard Worker internal::TrackEventInternal::SetClockId(
55*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
56*6dbdd20aSAndroid Build Coastguard Worker } else if (args.use_monotonic_raw_clock) {
57*6dbdd20aSAndroid Build Coastguard Worker internal::TrackEventInternal::SetClockId(
58*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW);
59*6dbdd20aSAndroid Build Coastguard Worker }
60*6dbdd20aSAndroid Build Coastguard Worker
61*6dbdd20aSAndroid Build Coastguard Worker if (args.disallow_merging_with_system_tracks) {
62*6dbdd20aSAndroid Build Coastguard Worker internal::TrackEventInternal::SetDisallowMergingWithSystemTracks(true);
63*6dbdd20aSAndroid Build Coastguard Worker }
64*6dbdd20aSAndroid Build Coastguard Worker }
65*6dbdd20aSAndroid Build Coastguard Worker
66*6dbdd20aSAndroid Build Coastguard Worker internal::TracingMuxerImpl::InitializeInstance(args);
67*6dbdd20aSAndroid Build Coastguard Worker internal::TrackRegistry::InitializeInstance();
68*6dbdd20aSAndroid Build Coastguard Worker g_was_initialized = true;
69*6dbdd20aSAndroid Build Coastguard Worker }
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Worker // static
IsInitialized()72*6dbdd20aSAndroid Build Coastguard Worker bool Tracing::IsInitialized() {
73*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(InitializedMutex());
74*6dbdd20aSAndroid Build Coastguard Worker return g_was_initialized;
75*6dbdd20aSAndroid Build Coastguard Worker }
76*6dbdd20aSAndroid Build Coastguard Worker
77*6dbdd20aSAndroid Build Coastguard Worker // static
Shutdown()78*6dbdd20aSAndroid Build Coastguard Worker void Tracing::Shutdown() {
79*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(InitializedMutex());
80*6dbdd20aSAndroid Build Coastguard Worker if (!g_was_initialized)
81*6dbdd20aSAndroid Build Coastguard Worker return;
82*6dbdd20aSAndroid Build Coastguard Worker internal::TracingMuxerImpl::Shutdown();
83*6dbdd20aSAndroid Build Coastguard Worker g_was_initialized = false;
84*6dbdd20aSAndroid Build Coastguard Worker }
85*6dbdd20aSAndroid Build Coastguard Worker
86*6dbdd20aSAndroid Build Coastguard Worker // static
ResetForTesting()87*6dbdd20aSAndroid Build Coastguard Worker void Tracing::ResetForTesting() {
88*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(InitializedMutex());
89*6dbdd20aSAndroid Build Coastguard Worker if (!g_was_initialized)
90*6dbdd20aSAndroid Build Coastguard Worker return;
91*6dbdd20aSAndroid Build Coastguard Worker base::SetLogMessageCallback(nullptr);
92*6dbdd20aSAndroid Build Coastguard Worker internal::TracingMuxerImpl::ResetForTesting();
93*6dbdd20aSAndroid Build Coastguard Worker internal::TrackRegistry::ResetForTesting();
94*6dbdd20aSAndroid Build Coastguard Worker g_was_initialized = false;
95*6dbdd20aSAndroid Build Coastguard Worker }
96*6dbdd20aSAndroid Build Coastguard Worker
97*6dbdd20aSAndroid Build Coastguard Worker // static
NewTraceInternal(BackendType backend,TracingConsumerBackend * (* system_backend_factory)())98*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<TracingSession> Tracing::NewTraceInternal(
99*6dbdd20aSAndroid Build Coastguard Worker BackendType backend,
100*6dbdd20aSAndroid Build Coastguard Worker TracingConsumerBackend* (*system_backend_factory)()) {
101*6dbdd20aSAndroid Build Coastguard Worker return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
102*6dbdd20aSAndroid Build Coastguard Worker ->CreateTracingSession(backend, system_backend_factory);
103*6dbdd20aSAndroid Build Coastguard Worker }
104*6dbdd20aSAndroid Build Coastguard Worker
105*6dbdd20aSAndroid Build Coastguard Worker // static
SetupStartupTracing(const TraceConfig & config,Tracing::SetupStartupTracingOpts opts)106*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<StartupTracingSession> Tracing::SetupStartupTracing(
107*6dbdd20aSAndroid Build Coastguard Worker const TraceConfig& config,
108*6dbdd20aSAndroid Build Coastguard Worker Tracing::SetupStartupTracingOpts opts) {
109*6dbdd20aSAndroid Build Coastguard Worker return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
110*6dbdd20aSAndroid Build Coastguard Worker ->CreateStartupTracingSession(config, std::move(opts));
111*6dbdd20aSAndroid Build Coastguard Worker }
112*6dbdd20aSAndroid Build Coastguard Worker
113*6dbdd20aSAndroid Build Coastguard Worker // static
SetupStartupTracingBlocking(const TraceConfig & config,Tracing::SetupStartupTracingOpts opts)114*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<StartupTracingSession> Tracing::SetupStartupTracingBlocking(
115*6dbdd20aSAndroid Build Coastguard Worker const TraceConfig& config,
116*6dbdd20aSAndroid Build Coastguard Worker Tracing::SetupStartupTracingOpts opts) {
117*6dbdd20aSAndroid Build Coastguard Worker return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
118*6dbdd20aSAndroid Build Coastguard Worker ->CreateStartupTracingSessionBlocking(config, std::move(opts));
119*6dbdd20aSAndroid Build Coastguard Worker }
120*6dbdd20aSAndroid Build Coastguard Worker
121*6dbdd20aSAndroid Build Coastguard Worker // static
ActivateTriggers(const std::vector<std::string> & triggers,uint32_t ttl_ms)122*6dbdd20aSAndroid Build Coastguard Worker void Tracing::ActivateTriggers(const std::vector<std::string>& triggers,
123*6dbdd20aSAndroid Build Coastguard Worker uint32_t ttl_ms) {
124*6dbdd20aSAndroid Build Coastguard Worker internal::TracingMuxer::Get()->ActivateTriggers(triggers, ttl_ms);
125*6dbdd20aSAndroid Build Coastguard Worker }
126*6dbdd20aSAndroid Build Coastguard Worker
127*6dbdd20aSAndroid Build Coastguard Worker TracingSession::~TracingSession() = default;
128*6dbdd20aSAndroid Build Coastguard Worker
CloneTrace(CloneTraceArgs,CloneTraceCallback)129*6dbdd20aSAndroid Build Coastguard Worker void TracingSession::CloneTrace(CloneTraceArgs, CloneTraceCallback) {}
130*6dbdd20aSAndroid Build Coastguard Worker
131*6dbdd20aSAndroid Build Coastguard Worker // Can be called from any thread.
FlushBlocking(uint32_t timeout_ms)132*6dbdd20aSAndroid Build Coastguard Worker bool TracingSession::FlushBlocking(uint32_t timeout_ms) {
133*6dbdd20aSAndroid Build Coastguard Worker std::atomic<bool> flush_result;
134*6dbdd20aSAndroid Build Coastguard Worker base::WaitableEvent flush_ack;
135*6dbdd20aSAndroid Build Coastguard Worker
136*6dbdd20aSAndroid Build Coastguard Worker // The non blocking Flush() can be called on any thread. It does the PostTask
137*6dbdd20aSAndroid Build Coastguard Worker // internally.
138*6dbdd20aSAndroid Build Coastguard Worker Flush(
139*6dbdd20aSAndroid Build Coastguard Worker [&flush_ack, &flush_result](bool res) {
140*6dbdd20aSAndroid Build Coastguard Worker flush_result = res;
141*6dbdd20aSAndroid Build Coastguard Worker flush_ack.Notify();
142*6dbdd20aSAndroid Build Coastguard Worker },
143*6dbdd20aSAndroid Build Coastguard Worker timeout_ms);
144*6dbdd20aSAndroid Build Coastguard Worker flush_ack.Wait();
145*6dbdd20aSAndroid Build Coastguard Worker return flush_result;
146*6dbdd20aSAndroid Build Coastguard Worker }
147*6dbdd20aSAndroid Build Coastguard Worker
ReadTraceBlocking()148*6dbdd20aSAndroid Build Coastguard Worker std::vector<char> TracingSession::ReadTraceBlocking() {
149*6dbdd20aSAndroid Build Coastguard Worker std::vector<char> raw_trace;
150*6dbdd20aSAndroid Build Coastguard Worker std::mutex mutex;
151*6dbdd20aSAndroid Build Coastguard Worker std::condition_variable cv;
152*6dbdd20aSAndroid Build Coastguard Worker
153*6dbdd20aSAndroid Build Coastguard Worker bool all_read = false;
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker ReadTrace([&mutex, &raw_trace, &all_read, &cv](ReadTraceCallbackArgs cb) {
156*6dbdd20aSAndroid Build Coastguard Worker raw_trace.insert(raw_trace.end(), cb.data, cb.data + cb.size);
157*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
158*6dbdd20aSAndroid Build Coastguard Worker all_read = !cb.has_more;
159*6dbdd20aSAndroid Build Coastguard Worker if (all_read)
160*6dbdd20aSAndroid Build Coastguard Worker cv.notify_one();
161*6dbdd20aSAndroid Build Coastguard Worker });
162*6dbdd20aSAndroid Build Coastguard Worker
163*6dbdd20aSAndroid Build Coastguard Worker {
164*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
165*6dbdd20aSAndroid Build Coastguard Worker cv.wait(lock, [&all_read] { return all_read; });
166*6dbdd20aSAndroid Build Coastguard Worker }
167*6dbdd20aSAndroid Build Coastguard Worker return raw_trace;
168*6dbdd20aSAndroid Build Coastguard Worker }
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker TracingSession::GetTraceStatsCallbackArgs
GetTraceStatsBlocking()171*6dbdd20aSAndroid Build Coastguard Worker TracingSession::GetTraceStatsBlocking() {
172*6dbdd20aSAndroid Build Coastguard Worker std::mutex mutex;
173*6dbdd20aSAndroid Build Coastguard Worker std::condition_variable cv;
174*6dbdd20aSAndroid Build Coastguard Worker GetTraceStatsCallbackArgs result;
175*6dbdd20aSAndroid Build Coastguard Worker bool stats_read = false;
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard Worker GetTraceStats(
178*6dbdd20aSAndroid Build Coastguard Worker [&mutex, &result, &stats_read, &cv](GetTraceStatsCallbackArgs args) {
179*6dbdd20aSAndroid Build Coastguard Worker result = std::move(args);
180*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
181*6dbdd20aSAndroid Build Coastguard Worker stats_read = true;
182*6dbdd20aSAndroid Build Coastguard Worker cv.notify_one();
183*6dbdd20aSAndroid Build Coastguard Worker });
184*6dbdd20aSAndroid Build Coastguard Worker
185*6dbdd20aSAndroid Build Coastguard Worker {
186*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
187*6dbdd20aSAndroid Build Coastguard Worker cv.wait(lock, [&stats_read] { return stats_read; });
188*6dbdd20aSAndroid Build Coastguard Worker }
189*6dbdd20aSAndroid Build Coastguard Worker return result;
190*6dbdd20aSAndroid Build Coastguard Worker }
191*6dbdd20aSAndroid Build Coastguard Worker
192*6dbdd20aSAndroid Build Coastguard Worker TracingSession::QueryServiceStateCallbackArgs
QueryServiceStateBlocking()193*6dbdd20aSAndroid Build Coastguard Worker TracingSession::QueryServiceStateBlocking() {
194*6dbdd20aSAndroid Build Coastguard Worker std::mutex mutex;
195*6dbdd20aSAndroid Build Coastguard Worker std::condition_variable cv;
196*6dbdd20aSAndroid Build Coastguard Worker QueryServiceStateCallbackArgs result;
197*6dbdd20aSAndroid Build Coastguard Worker bool status_read = false;
198*6dbdd20aSAndroid Build Coastguard Worker
199*6dbdd20aSAndroid Build Coastguard Worker QueryServiceState(
200*6dbdd20aSAndroid Build Coastguard Worker [&mutex, &result, &status_read, &cv](QueryServiceStateCallbackArgs args) {
201*6dbdd20aSAndroid Build Coastguard Worker result = std::move(args);
202*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
203*6dbdd20aSAndroid Build Coastguard Worker status_read = true;
204*6dbdd20aSAndroid Build Coastguard Worker cv.notify_one();
205*6dbdd20aSAndroid Build Coastguard Worker });
206*6dbdd20aSAndroid Build Coastguard Worker
207*6dbdd20aSAndroid Build Coastguard Worker {
208*6dbdd20aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mutex);
209*6dbdd20aSAndroid Build Coastguard Worker cv.wait(lock, [&status_read] { return status_read; });
210*6dbdd20aSAndroid Build Coastguard Worker }
211*6dbdd20aSAndroid Build Coastguard Worker return result;
212*6dbdd20aSAndroid Build Coastguard Worker }
213*6dbdd20aSAndroid Build Coastguard Worker
214*6dbdd20aSAndroid Build Coastguard Worker StartupTracingSession::~StartupTracingSession() = default;
215*6dbdd20aSAndroid Build Coastguard Worker
216*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
217