| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "perfetto/public/abi/tracing_session_abi.h" |
| |
| #include <condition_variable> |
| #include <mutex> |
| |
| #include "perfetto/tracing/tracing.h" |
| #include "protos/perfetto/config/trace_config.gen.h" |
| |
| struct PerfettoTracingSessionImpl* PerfettoTracingSessionSystemCreate() { |
| std::unique_ptr<perfetto::TracingSession> tracing_session = |
| perfetto::Tracing::NewTrace(perfetto::kSystemBackend); |
| return reinterpret_cast<struct PerfettoTracingSessionImpl*>( |
| tracing_session.release()); |
| } |
| |
| struct PerfettoTracingSessionImpl* PerfettoTracingSessionInProcessCreate() { |
| std::unique_ptr<perfetto::TracingSession> tracing_session = |
| perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); |
| return reinterpret_cast<struct PerfettoTracingSessionImpl*>( |
| tracing_session.release()); |
| } |
| |
| void PerfettoTracingSessionSetup(struct PerfettoTracingSessionImpl* session, |
| void* cfg_begin, |
| size_t cfg_len) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| perfetto::TraceConfig cfg; |
| cfg.ParseFromArray(cfg_begin, cfg_len); |
| ts->Setup(cfg); |
| } |
| |
| void PerfettoTracingSessionSetStopCb(struct PerfettoTracingSessionImpl* session, |
| PerfettoTracingSessionStopCb cb, |
| void* user_arg) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| ts->SetOnStopCallback([session, cb, user_arg]() { cb(session, user_arg); }); |
| } |
| |
| void PerfettoTracingSessionStartAsync( |
| struct PerfettoTracingSessionImpl* session) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| ts->Start(); |
| } |
| |
| void PerfettoTracingSessionStartBlocking( |
| struct PerfettoTracingSessionImpl* session) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| ts->StartBlocking(); |
| } |
| |
| void PerfettoTracingSessionFlushAsync( |
| struct PerfettoTracingSessionImpl* session, |
| uint32_t timeout_ms, |
| PerfettoTracingSessionFlushCb cb, |
| void* user_arg) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| std::function<void(bool)> flush_cb = [](bool) {}; |
| if (cb) { |
| flush_cb = [cb, session, user_arg](bool success) { |
| cb(session, success, user_arg); |
| }; |
| } |
| ts->Flush(std::move(flush_cb), timeout_ms); |
| } |
| |
| bool PerfettoTracingSessionFlushBlocking( |
| struct PerfettoTracingSessionImpl* session, |
| uint32_t timeout_ms) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| return ts->FlushBlocking(timeout_ms); |
| } |
| |
| void PerfettoTracingSessionStopAsync( |
| struct PerfettoTracingSessionImpl* session) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| ts->Stop(); |
| } |
| |
| void PerfettoTracingSessionStopBlocking( |
| struct PerfettoTracingSessionImpl* session) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| ts->StopBlocking(); |
| } |
| |
| void PerfettoTracingSessionReadTraceBlocking( |
| struct PerfettoTracingSessionImpl* session, |
| PerfettoTracingSessionReadCb callback, |
| void* user_arg) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| |
| std::mutex mutex; |
| std::condition_variable cv; |
| |
| bool all_read = false; |
| |
| ts->ReadTrace([&mutex, &all_read, &cv, session, callback, user_arg]( |
| perfetto::TracingSession::ReadTraceCallbackArgs args) { |
| callback(session, static_cast<const void*>(args.data), args.size, |
| args.has_more, user_arg); |
| std::unique_lock<std::mutex> lock(mutex); |
| all_read = !args.has_more; |
| if (all_read) |
| cv.notify_one(); |
| }); |
| |
| { |
| std::unique_lock<std::mutex> lock(mutex); |
| cv.wait(lock, [&all_read] { return all_read; }); |
| } |
| } |
| |
| void PerfettoTracingSessionDestroy(struct PerfettoTracingSessionImpl* session) { |
| auto* ts = reinterpret_cast<perfetto::TracingSession*>(session); |
| delete ts; |
| } |