blob: 42dccf7851be2ff5715ce94c582a30df96d3206d [file] [log] [blame]
// Copyright 2023 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.
#ifndef SRC_PERFORMANCE_EXPERIMENTAL_PROFILER_SAMPLER_H_
#define SRC_PERFORMANCE_EXPERIMENTAL_PROFILER_SAMPLER_H_
#include <fidl/fuchsia.cpu.profiler/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/dispatcher.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/process.h>
#include <lib/zx/result.h>
#include <lib/zx/task.h>
#include <lib/zx/thread.h>
#include <lib/zxdump/elf-search.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <memory>
#include <unordered_map>
#include <vector>
#include <src/lib/unwinder/cfi_unwinder.h>
#include <src/lib/unwinder/fp_unwinder.h>
#include <src/lib/unwinder/fuchsia.h>
#include <src/lib/unwinder/unwind.h>
#include "job_watcher.h"
#include "process_watcher.h"
#include "symbolization_context.h"
#include "targets.h"
namespace profiler {
struct Sample {
zx_koid_t pid;
zx_koid_t tid;
std::vector<uint64_t> stack;
};
class Sampler {
public:
explicit Sampler(async_dispatcher_t* dispatcher, TargetTree targets,
std::vector<fuchsia_cpu_profiler::SamplingConfig> sample_specs)
: dispatcher_(dispatcher),
targets_(std::move(targets)),
sample_specs_(std::move(sample_specs)) {}
virtual zx::result<> Start(size_t buffer_size_mb);
virtual zx::result<> Stop();
// Return the information needed to symbolize the samples
zx::result<profiler::SymbolizationContext> GetContexts();
std::unordered_map<zx_koid_t, std::vector<Sample>> GetSamples() { return samples_; }
std::vector<zx::ticks> SamplingDurations() { return inspecting_durations_; }
virtual zx::result<> AddTarget(JobTarget&& target);
virtual ~Sampler() = default;
protected:
zx::result<> WatchTarget(const JobTarget& target);
virtual void AddThread(std::vector<const zx_koid_t> job_path, zx_koid_t pid, zx_koid_t tid,
zx::thread t);
virtual void RemoveThread(std::vector<const zx_koid_t> job_path, zx_koid_t pid, zx_koid_t tid);
void CollectSamples(async_dispatcher_t* dispatcher, async::TaskBase* task, zx_status_t status);
async_dispatcher_t* dispatcher_;
async::TaskMethod<profiler::Sampler, &profiler::Sampler::CollectSamples> sample_task_{this};
TargetTree targets_;
std::vector<fuchsia_cpu_profiler::SamplingConfig> sample_specs_;
std::vector<zx::ticks> inspecting_durations_;
std::unordered_map<zx_koid_t, std::vector<Sample>> samples_;
// Watchers cannot be moved, so we need to box them
std::unordered_map<zx_koid_t, std::unique_ptr<ProcessWatcher>> process_watchers_;
std::unordered_map<zx_koid_t, std::unique_ptr<JobWatcher>> job_watchers_;
};
} // namespace profiler
#endif // SRC_PERFORMANCE_EXPERIMENTAL_PROFILER_SAMPLER_H_