| /* |
| * 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/backend_type.h" |
| #include "perfetto/tracing/tracing.h" |
| #include "protos/perfetto/config/trace_config.gen.h" |
| |
| struct PerfettoTracingSessionImpl* PerfettoTracingSessionCreate( |
| PerfettoBackendTypes backend) { |
| uint32_t backend_type = 0; |
| if (backend & PERFETTO_BACKEND_IN_PROCESS) { |
| backend_type |= perfetto::kInProcessBackend; |
| } |
| if (backend & PERFETTO_BACKEND_SYSTEM) { |
| backend_type |= perfetto::kSystemBackend; |
| } |
| std::unique_ptr<perfetto::TracingSession> tracing_session = |
| perfetto::Tracing::NewTrace( |
| static_cast<perfetto::BackendType>(backend_type)); |
| 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 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 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; |
| } |