blob: 7bf7175db8581df6b0f081c497fd2505d0b20c82 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/sync/completion.h>
#include <lib/trace-provider/provider.h>
#include <lib/trace-provider/start.h>
#include <lib/trace/observer.h>
#include <lib/zx/process.h>
#include <memory>
#include <thread>
namespace {
bool CreateProvider(async_dispatcher_t* dispatcher,
std::unique_ptr<trace::TraceProviderWithFdio>* out_provider,
bool* out_manager_is_tracing_already) {
// Get the current process's name. This is based on what
// trace_provider_create_with_fdio() does.
zx::unowned<zx::process> process = zx::process::self();
char process_name[ZX_MAX_NAME_LEN];
if (process->get_property(ZX_PROP_NAME, process_name, sizeof(process_name)) != ZX_OK) {
return false;
}
return trace::TraceProviderWithFdio::CreateSynchronously(dispatcher, process_name, out_provider,
out_manager_is_tracing_already);
}
// Implements a thread that runs a TraceProvider. It signals |completion|
// when its setup is complete.
void TraceProviderThread(sync_completion_t* completion) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
std::unique_ptr<trace::TraceProviderWithFdio> provider;
bool manager_is_tracing_already;
if (!CreateProvider(loop.dispatcher(), &provider, &manager_is_tracing_already)) {
sync_completion_signal(completion);
return;
}
trace::TraceObserver trace_observer;
if (manager_is_tracing_already) {
// Tracing is already enabled in the trace manager. Wait for our
// process's setup of tracing to complete.
trace_observer.Start(loop.dispatcher(), [&] {
// This callback may get called multiple times, but we must only
// signal |completion| once because signalling it will cause it to be
// deallocated.
if (completion) {
sync_completion_signal(completion);
completion = nullptr;
}
// We would like to unregister the TraceObserver by doing
// trace_observer.Stop(), but that triggers a ZX_ERR_BAD_HANDLE in
// the event loop.
});
} else {
// Tracing is not currently enabled in the trace manager, so no
// further setup is required.
sync_completion_signal(completion);
}
loop.Run();
}
} // namespace
void trace_provider_start() {
sync_completion_t completion;
std::thread thread(TraceProviderThread, &completion);
thread.detach();
sync_completion_wait(&completion, ZX_TIME_INFINITE);
}