Commit eb9eb9b1 authored by Mike Wittman's avatar Mike Wittman Committed by Commit Bot

[Sampling profiler] Introduce ThreadToken representation

The stack sampling implementations for Linux and Android platforms require
the pthread_t type to obtain the stack base address, in addition to the
PlatformThreadId. This change introduces a minimal ThreadToken abstraction
that encapsulates the necessary thread state across platforms.

TBR=gab@chromium.org

Bug: 988579
Change-Id: Ie5d70709ddae362ca414dc5a635e456c8bd9f8ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1860151Reviewed-by: default avatarMike Wittman <wittman@chromium.org>
Reviewed-by: default avatarssid <ssid@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarCharlie Andrews <charliea@chromium.org>
Commit-Queue: Mike Wittman <wittman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709061}
parent 42f3f2e6
......@@ -616,6 +616,8 @@ jumbo_component("base") {
"profiler/register_context.h",
"profiler/sample_metadata.cc",
"profiler/sample_metadata.h",
"profiler/sampling_profiler_thread_token.cc",
"profiler/sampling_profiler_thread_token.h",
"profiler/stack_buffer.cc",
"profiler/stack_buffer.h",
"profiler/stack_copier.cc",
......
// Copyright 2019 The Chromium 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 "base/profiler/sampling_profiler_thread_token.h"
namespace base {
SamplingProfilerThreadToken GetSamplingProfilerCurrentThreadToken() {
#if defined(OS_ANDROID) || defined(OS_LINUX)
return {PlatformThread::CurrentId(), pthread_self()};
#else
return {PlatformThread::CurrentId()};
#endif
}
} // namespace base
// Copyright 2019 The Chromium 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 BASE_PROFILER_SAMPLING_PROFILER_THREAD_TOKEN_H_
#define BASE_PROFILER_SAMPLING_PROFILER_THREAD_TOKEN_H_
#include "base/base_export.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#if defined(OS_ANDROID) || defined(OS_LINUX)
#include <pthread.h>
#endif
namespace base {
// SamplingProfilerThreadToken represents the thread identifier(s) required by
// sampling profiler to operate on a thread. PlatformThreadId is needed for all
// platforms, while non-Mac POSIX also requires a pthread_t to pass to pthread
// functions used to obtain the stack base address.
struct SamplingProfilerThreadToken {
PlatformThreadId id;
#if defined(OS_ANDROID) || defined(OS_LINUX)
pthread_t pthread_id;
#endif
};
BASE_EXPORT SamplingProfilerThreadToken GetSamplingProfilerCurrentThreadToken();
} // namespace base
#endif // BASE_PROFILER_SAMPLING_PROFILER_THREAD_TOKEN_H_
......@@ -9,6 +9,7 @@
#include "base/base_export.h"
#include "base/macros.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/threading/platform_thread.h"
namespace base {
......@@ -26,10 +27,11 @@ class BASE_EXPORT StackSampler {
public:
virtual ~StackSampler();
// Creates a stack sampler that records samples for thread with |thread_id|.
// Returns null if this platform does not support stack sampling.
// Creates a stack sampler that records samples for thread with
// |thread_token|. Returns null if this platform does not support stack
// sampling.
static std::unique_ptr<StackSampler> Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate);
......
......@@ -15,12 +15,12 @@
namespace base {
std::unique_ptr<StackSampler> StackSampler::Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) {
return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSignal>(
std::make_unique<ThreadDelegatePosix>(thread_id)),
std::make_unique<ThreadDelegatePosix>(thread_token)),
std::make_unique<NativeUnwinderAndroid>(), module_cache, test_delegate);
}
......
......@@ -11,7 +11,7 @@ namespace base {
// static
std::unique_ptr<StackSampler> StackSampler::Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) {
return nullptr;
......
......@@ -13,12 +13,12 @@ namespace base {
// static
std::unique_ptr<StackSampler> StackSampler::Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) {
return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSuspend>(
std::make_unique<SuspendableThreadDelegateMac>(thread_id)),
std::make_unique<SuspendableThreadDelegateMac>(thread_token)),
std::make_unique<NativeUnwinderMac>(module_cache), module_cache,
test_delegate);
}
......
......@@ -12,7 +12,7 @@
namespace base {
std::unique_ptr<StackSampler> StackSampler::Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) {
return nullptr;
......
......@@ -14,13 +14,13 @@ namespace base {
// static
std::unique_ptr<StackSampler> StackSampler::Create(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate) {
#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64)
return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSuspend>(
std::make_unique<SuspendableThreadDelegateWin>(thread_id)),
std::make_unique<SuspendableThreadDelegateWin>(thread_token)),
std::make_unique<NativeUnwinderWin>(), module_cache, test_delegate);
#else
return nullptr;
......
......@@ -79,13 +79,11 @@ class StackSamplingProfiler::SamplingThread : public Thread {
};
struct CollectionContext {
CollectionContext(PlatformThreadId target,
const SamplingParams& params,
CollectionContext(const SamplingParams& params,
WaitableEvent* finished,
std::unique_ptr<StackSampler> sampler,
std::unique_ptr<ProfileBuilder> profile_builder)
: collection_id(next_collection_id.GetNext()),
target(target),
params(params),
finished(finished),
sampler(std::move(sampler)),
......@@ -96,7 +94,6 @@ class StackSamplingProfiler::SamplingThread : public Thread {
// collection to outside interests.
const int collection_id;
const PlatformThreadId target; // ID of The thread being sampled.
const SamplingParams params; // Information about how to sample.
WaitableEvent* const finished; // Signaled when all sampling complete.
......@@ -649,23 +646,23 @@ void StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
}
StackSamplingProfiler::StackSamplingProfiler(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
std::unique_ptr<ProfileBuilder> profile_builder,
StackSamplerTestDelegate* test_delegate)
: StackSamplingProfiler(thread_id,
: StackSamplingProfiler(thread_token,
params,
std::move(profile_builder),
nullptr,
test_delegate) {}
StackSamplingProfiler::StackSamplingProfiler(
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
std::unique_ptr<ProfileBuilder> profile_builder,
std::unique_ptr<StackSampler> sampler,
StackSamplerTestDelegate* test_delegate)
: thread_id_(thread_id),
: thread_token_(thread_token),
params_(params),
profile_builder_(std::move(profile_builder)),
sampler_(std::move(sampler)),
......@@ -712,7 +709,7 @@ void StackSamplingProfiler::Start() {
if (!sampler_)
sampler_ = StackSampler::Create(
thread_id_, profile_builder_->GetModuleCache(), test_delegate_);
thread_token_, profile_builder_->GetModuleCache(), test_delegate_);
if (!sampler_)
return;
......@@ -735,7 +732,7 @@ void StackSamplingProfiler::Start() {
DCHECK_EQ(kNullProfilerId, profiler_id_);
profiler_id_ = SamplingThread::GetInstance()->Add(
std::make_unique<SamplingThread::CollectionContext>(
thread_id_, params_, &profiling_inactive_, std::move(sampler_),
params_, &profiling_inactive_, std::move(sampler_),
std::move(profile_builder_)));
DCHECK_NE(kNullProfilerId, profiler_id_);
......
......@@ -11,6 +11,7 @@
#include "base/base_export.h"
#include "base/macros.h"
#include "base/profiler/profile_builder.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
......@@ -86,14 +87,14 @@ class BASE_EXPORT StackSamplingProfiler {
//
// The caller must ensure that this object gets destroyed before the thread
// exits.
StackSamplingProfiler(PlatformThreadId thread_id,
StackSamplingProfiler(SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
std::unique_ptr<ProfileBuilder> profile_builder,
StackSamplerTestDelegate* test_delegate = nullptr);
// Same as above function, with custom |sampler| implementation. The sampler
// on Android is not implemented in base.
StackSamplingProfiler(PlatformThreadId thread_id,
StackSamplingProfiler(SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
std::unique_ptr<ProfileBuilder> profile_builder,
std::unique_ptr<StackSampler> sampler,
......@@ -157,7 +158,7 @@ class BASE_EXPORT StackSamplingProfiler {
class SamplingThread;
// The thread whose stack will be sampled.
PlatformThreadId thread_id_;
SamplingProfilerThreadToken thread_token_;
const SamplingParams params_;
......
......@@ -61,7 +61,7 @@ TargetThread::TargetThread(OnceClosure to_run) : to_run_(std::move(to_run)) {}
TargetThread::~TargetThread() = default;
void TargetThread::ThreadMain() {
id_ = PlatformThread::CurrentId();
thread_token_ = GetSamplingProfilerCurrentThreadToken();
std::move(to_run_).Run();
}
......@@ -144,7 +144,7 @@ void WithTargetThread(UnwindScenario* scenario,
events.ready_for_sample.Wait();
std::move(profile_callback).Run(target_thread.id());
std::move(profile_callback).Run(target_thread.thread_token());
events.sample_finished.Signal();
......@@ -160,12 +160,14 @@ std::vector<Frame> SampleScenario(UnwindScenario* scenario,
std::vector<Frame> sample;
WithTargetThread(
scenario, BindLambdaForTesting([&](PlatformThreadId target_thread_id) {
scenario,
BindLambdaForTesting(
[&](SamplingProfilerThreadToken target_thread_token) {
WaitableEvent sampling_thread_completed(
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler(
target_thread_id, params,
target_thread_token, params,
std::make_unique<TestProfileBuilder>(
module_cache,
BindLambdaForTesting([&sample, &sampling_thread_completed](
......
......@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/profiler/frame.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
......@@ -26,10 +27,10 @@ class TargetThread : public PlatformThread::Delegate {
// PlatformThread::Delegate:
void ThreadMain() override;
PlatformThreadId id() const { return id_; }
SamplingProfilerThreadToken thread_token() const { return thread_token_; }
private:
PlatformThreadId id_ = 0;
SamplingProfilerThreadToken thread_token_ = {0};
OnceClosure to_run_;
DISALLOW_COPY_AND_ASSIGN(TargetThread);
......@@ -91,7 +92,7 @@ class UnwindScenario {
FunctionAddressRange CallWithPlainFunction(OnceClosure wait_for_sample);
// The callback to perform profiling on the provided thread.
using ProfileCallback = OnceCallback<void(PlatformThreadId)>;
using ProfileCallback = OnceCallback<void(SamplingProfilerThreadToken)>;
// Executes |profile_callback| while running |scenario| on the target
// thread. Performs all necessary target thread startup and shutdown work before
......
......@@ -270,13 +270,13 @@ void WithTargetThread(ProfileCallback profile_callback) {
}
struct TestProfilerInfo {
TestProfilerInfo(PlatformThreadId thread_id,
TestProfilerInfo(SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
ModuleCache* module_cache,
StackSamplerTestDelegate* delegate = nullptr)
: completed(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED),
profiler(thread_id,
profiler(thread_token,
params,
std::make_unique<TestProfileBuilder>(
module_cache,
......@@ -298,15 +298,15 @@ struct TestProfilerInfo {
// Creates multiple profilers based on a vector of parameters.
std::vector<std::unique_ptr<TestProfilerInfo>> CreateProfilers(
PlatformThreadId target_thread_id,
SamplingProfilerThreadToken target_thread_token,
const std::vector<SamplingParams>& params,
ModuleCache* module_cache) {
DCHECK(!params.empty());
std::vector<std::unique_ptr<TestProfilerInfo>> profilers;
for (const auto& i : params) {
profilers.push_back(
std::make_unique<TestProfilerInfo>(target_thread_id, i, module_cache));
profilers.push_back(std::make_unique<TestProfilerInfo>(target_thread_token,
i, module_cache));
}
return profilers;
......@@ -318,8 +318,9 @@ std::vector<std::vector<Frame>> CaptureSamples(const SamplingParams& params,
TimeDelta profiler_wait_time,
ModuleCache* module_cache) {
std::vector<std::vector<Frame>> samples;
WithTargetThread(BindLambdaForTesting([&](PlatformThreadId target_thread_id) {
TestProfilerInfo info(target_thread_id, params, module_cache);
WithTargetThread(BindLambdaForTesting(
[&](SamplingProfilerThreadToken target_thread_token) {
TestProfilerInfo info(target_thread_token, params, module_cache);
info.profiler.Start();
info.completed.TimedWait(profiler_wait_time);
info.profiler.Stop();
......@@ -408,7 +409,7 @@ void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) {
StackCopiedSignaler test_delegate(&stack_copied, &start_stack_walk,
wait_until_unloaded);
StackSamplingProfiler profiler(
target_thread.id(), params,
target_thread.thread_token(), params,
std::make_unique<TestProfileBuilder>(
module_cache,
BindLambdaForTesting(
......@@ -618,18 +619,19 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
// Checks that a profiler can stop/destruct without ever having started.
PROFILER_TEST_F(StackSamplingProfilerTest, StopWithoutStarting) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params;
params.sampling_interval = TimeDelta::FromMilliseconds(0);
params.samples_per_profile = 1;
Profile profile;
WaitableEvent sampling_completed(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent sampling_completed(
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler(
target_thread_id, params,
target_thread_token, params,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
......@@ -666,8 +668,8 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
size_t count_ = 0;
};
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params[2];
// Providing an initial delay makes it more likely that both will be
......@@ -684,37 +686,38 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
SampleRecordedCounter samples_recorded[size(params)];
TestProfilerInfo profiler_info0(target_thread_id, params[0], module_cache(),
&samples_recorded[0]);
TestProfilerInfo profiler_info1(target_thread_id, params[1], module_cache(),
&samples_recorded[1]);
TestProfilerInfo profiler_info0(target_thread_token, params[0],
module_cache(), &samples_recorded[0]);
TestProfilerInfo profiler_info1(target_thread_token, params[1],
module_cache(), &samples_recorded[1]);
profiler_info0.profiler.Start();
profiler_info1.profiler.Start();
// Wait for both to start accumulating samples. Using a WaitableEvent is
// possible but gets complicated later on because there's no way of knowing
// if 0 or 1 additional sample will be taken after Stop() and thus no way
// of knowing how many Wait() calls to make on it.
// possible but gets complicated later on because there's no way of
// knowing if 0 or 1 additional sample will be taken after Stop() and
// thus no way of knowing how many Wait() calls to make on it.
while (samples_recorded[0].Get() == 0 || samples_recorded[1].Get() == 0)
PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
// Ensure that the first sampler can be safely stopped while the second
// continues to run. The stopped first profiler will still have a
// RecordSampleTask pending that will do nothing when executed because the
// collection will have been removed by Stop().
// RecordSampleTask pending that will do nothing when executed because
// the collection will have been removed by Stop().
profiler_info0.profiler.Stop();
profiler_info0.completed.Wait();
size_t count0 = samples_recorded[0].Get();
size_t count1 = samples_recorded[1].Get();
// Waiting for the second sampler to collect a couple samples ensures that
// the pending RecordSampleTask for the first has executed because tasks are
// always ordered by their next scheduled time.
// Waiting for the second sampler to collect a couple samples ensures
// that the pending RecordSampleTask for the first has executed because
// tasks are always ordered by their next scheduled time.
while (samples_recorded[1].Get() < count1 + 2)
PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
// Ensure that the first profiler didn't do anything since it was stopped.
// Ensure that the first profiler didn't do anything since it was
// stopped.
EXPECT_EQ(count0, samples_recorded[0].Get());
}));
}
......@@ -749,16 +752,16 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
WaitableEvent sample_recorded_;
};
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params;
params.sampling_interval = AVeryLongTimeDelta();
params.samples_per_profile = 2;
SampleRecordedEvent samples_recorded;
TestProfilerInfo profiler_info(target_thread_id, params, module_cache(),
&samples_recorded);
TestProfilerInfo profiler_info(target_thread_token, params,
module_cache(), &samples_recorded);
profiler_info.profiler.Start();
......@@ -779,15 +782,15 @@ PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
params.sampling_interval = TimeDelta::FromMilliseconds(10);
Profile profile;
WithTargetThread(BindLambdaForTesting([&, this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting([&, this](SamplingProfilerThreadToken
target_thread_token) {
std::unique_ptr<StackSamplingProfiler> profiler;
auto profile_builder = std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting([&profile](Profile result_profile) {
profile = std::move(result_profile);
}));
profiler.reset(new StackSamplingProfiler(target_thread_id, params,
profiler.reset(new StackSamplingProfiler(target_thread_token, params,
std::move(profile_builder)));
profiler->Start();
profiler.reset();
......@@ -814,8 +817,8 @@ PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
// Checks that a sampler can be started while another is running.
PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
WithTargetThread(
BindLambdaForTesting([this](PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
std::vector<SamplingParams> params(2);
params[0].initial_delay = AVeryLongTimeDelta();
......@@ -825,7 +828,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
params[1].samples_per_profile = 1;
std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
CreateProfilers(target_thread_id, params, module_cache());
CreateProfilers(target_thread_token, params, module_cache());
profiler_infos[0]->profiler.Start();
profiler_infos[1]->profiler.Start();
......@@ -838,19 +841,21 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
// correctly. Also checks that RecordMetadata() is invoked each time a sample
// is recorded.
PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params;
params.sampling_interval = TimeDelta::FromMilliseconds(1);
params.samples_per_profile = 3;
TestProfilerInfo profiler_info(target_thread_id, params, module_cache());
TestProfilerInfo profiler_info(target_thread_token, params,
module_cache());
profiler_info.profiler.Start();
profiler_info.completed.Wait();
EXPECT_EQ(3u, profiler_info.profile.samples.size());
// The profile duration should be greater than the total sampling intervals.
// The profile duration should be greater than the total sampling
// intervals.
EXPECT_GT(profiler_info.profile.profile_duration,
profiler_info.profile.sampling_period * 3);
......@@ -915,14 +920,15 @@ PROFILER_TEST_F(StackSamplingProfilerTest,
// Checks that it's safe to stop a task after it's completed and the sampling
// thread has shut-down for being idle.
PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params;
params.sampling_interval = TimeDelta::FromMilliseconds(1);
params.samples_per_profile = 1;
TestProfilerInfo profiler_info(target_thread_id, params, module_cache());
TestProfilerInfo profiler_info(target_thread_token, params,
module_cache());
profiler_info.profiler.Start();
profiler_info.completed.Wait();
......@@ -931,10 +937,11 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
// Perform an idle shutdown.
StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
false);
// Stop should be safe though its impossible to know at this moment if the
// sampling thread has completely exited or will just "stop soon".
// Stop should be safe though its impossible to know at this moment if
// the sampling thread has completely exited or will just "stop soon".
profiler_info.profiler.Stop();
}));
}
......@@ -943,8 +950,8 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
// started.
PROFILER_TEST_F(StackSamplingProfilerTest,
ProfileBeforeAndAfterSamplingThreadRunning) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
std::vector<SamplingParams> params(2);
params[0].initial_delay = AVeryLongTimeDelta();
......@@ -956,10 +963,12 @@ PROFILER_TEST_F(StackSamplingProfilerTest,
params[1].samples_per_profile = 1;
std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
CreateProfilers(target_thread_id, params, module_cache());
CreateProfilers(target_thread_token, params, module_cache());
// First profiler is started when there has never been a sampling thread.
EXPECT_FALSE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
// First profiler is started when there has never been a sampling
// thread.
EXPECT_FALSE(
StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
profiler_infos[0]->profiler.Start();
// Second profiler is started when sampling thread is already running.
EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
......@@ -974,14 +983,15 @@ PROFILER_TEST_F(StackSamplingProfilerTest,
// Checks that an idle-shutdown task will abort if a new profiler starts
// between when it was posted and when it runs.
PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
SamplingParams params;
params.sampling_interval = TimeDelta::FromMilliseconds(1);
params.samples_per_profile = 1;
TestProfilerInfo profiler_info(target_thread_id, params, module_cache());
TestProfilerInfo profiler_info(target_thread_token, params,
module_cache());
profiler_info.profiler.Start();
profiler_info.completed.Wait();
......@@ -989,18 +999,21 @@ PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
// Perform an idle shutdown but simulate that a new capture is started
// before it can actually run.
StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(true);
StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
true);
// Though the shutdown-task has been executed, any actual exit of the
// thread is asynchronous so there is no way to detect that *didn't* exit
// except to wait a reasonable amount of time and then check. Since the
// thread was just running ("perform" blocked until it was), it should
// finish almost immediately and without any waiting for tasks or events.
// thread is asynchronous so there is no way to detect that *didn't*
// exit except to wait a reasonable amount of time and then check. Since
// the thread was just running ("perform" blocked until it was), it
// should finish almost immediately and without any waiting for tasks or
// events.
PlatformThread::Sleep(TimeDelta::FromMilliseconds(200));
EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
// Ensure that it's still possible to run another sampler.
TestProfilerInfo another_info(target_thread_id, params, module_cache());
TestProfilerInfo another_info(target_thread_token, params,
module_cache());
another_info.profiler.Start();
another_info.completed.Wait();
EXPECT_EQ(1u, another_info.profile.samples.size());
......@@ -1009,8 +1022,8 @@ PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
// Checks that synchronized multiple sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
WithTargetThread(
BindLambdaForTesting([this](PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
std::vector<SamplingParams> params(2);
// Providing an initial delay makes it more likely that both will be
......@@ -1028,7 +1041,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
params[1].samples_per_profile = 8;
std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
CreateProfilers(target_thread_id, params, module_cache());
CreateProfilers(target_thread_token, params, module_cache());
profiler_infos[0]->profiler.Start();
profiler_infos[1]->profiler.Start();
......@@ -1048,8 +1061,8 @@ PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
// Checks that several mixed sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
WithTargetThread(BindLambdaForTesting([this](
PlatformThreadId target_thread_id) {
WithTargetThread(BindLambdaForTesting(
[this](SamplingProfilerThreadToken target_thread_token) {
std::vector<SamplingParams> params(3);
params[0].initial_delay = TimeDelta::FromMilliseconds(8);
......@@ -1065,15 +1078,17 @@ PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
params[2].samples_per_profile = 10;
std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
CreateProfilers(target_thread_id, params, module_cache());
CreateProfilers(target_thread_token, params, module_cache());
for (auto& i : profiler_infos)
i->profiler.Start();
// Wait for one profiler to finish.
size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
EXPECT_EQ(10u, profiler_infos[completed_profiler]->profile.samples.size());
// Stop and destroy all profilers, always in the same order. Don't crash.
EXPECT_EQ(10u,
profiler_infos[completed_profiler]->profile.samples.size());
// Stop and destroy all profilers, always in the same order. Don't
// crash.
for (auto& i : profiler_infos)
i->profiler.Stop();
for (auto& i : profiler_infos)
......@@ -1120,7 +1135,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler1(
target_thread1.id(), params1,
target_thread1.thread_token(), params1,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
......@@ -1133,7 +1148,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler2(
target_thread2.id(), params2,
target_thread2.thread_token(), params2,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
......@@ -1160,7 +1175,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
class ProfilerThread : public SimpleThread {
public:
ProfilerThread(const std::string& name,
PlatformThreadId thread_id,
SamplingProfilerThreadToken thread_token,
const SamplingParams& params,
ModuleCache* module_cache)
: SimpleThread(name, Options()),
......@@ -1168,7 +1183,7 @@ class ProfilerThread : public SimpleThread {
WaitableEvent::InitialState::NOT_SIGNALED),
completed_(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED),
profiler_(thread_id,
profiler_(thread_token,
params,
std::make_unique<TestProfileBuilder>(
module_cache,
......@@ -1198,7 +1213,8 @@ class ProfilerThread : public SimpleThread {
// Checks that different threads can run samplers in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
WithTargetThread(BindLambdaForTesting([](PlatformThreadId target_thread_id) {
WithTargetThread(
BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
// Providing an initial delay makes it more likely that both will be
// scheduled before either starts to run. Once started, samples will
// run ordered by their scheduled, interleaved times regardless of
......@@ -1213,11 +1229,11 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
// Start the profiler threads and give them a moment to get going.
ModuleCache module_cache1;
ProfilerThread profiler_thread1("profiler1", target_thread_id, params1,
&module_cache1);
ProfilerThread profiler_thread1("profiler1", target_thread_token,
params1, &module_cache1);
ModuleCache module_cache2;
ProfilerThread profiler_thread2("profiler2", target_thread_id, params2,
&module_cache2);
ProfilerThread profiler_thread2("profiler2", target_thread_token,
params2, &module_cache2);
profiler_thread1.Start();
profiler_thread2.Start();
PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
......@@ -1245,17 +1261,19 @@ PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_BeforeStart) {
UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
Profile profile;
WithTargetThread(&scenario, BindLambdaForTesting([&](PlatformThreadId
target_thread_id) {
WithTargetThread(
&scenario,
BindLambdaForTesting(
[&](SamplingProfilerThreadToken target_thread_token) {
WaitableEvent sampling_thread_completed(
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler(
target_thread_id, params,
target_thread_token, params,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
[&profile, &sampling_thread_completed](Profile result_profile) {
BindLambdaForTesting([&profile, &sampling_thread_completed](
Profile result_profile) {
profile = std::move(result_profile);
sampling_thread_completed.Signal();
})));
......@@ -1283,17 +1301,19 @@ PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStart) {
UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
Profile profile;
WithTargetThread(&scenario, BindLambdaForTesting([&](PlatformThreadId
target_thread_id) {
WithTargetThread(
&scenario,
BindLambdaForTesting(
[&](SamplingProfilerThreadToken target_thread_token) {
WaitableEvent sampling_thread_completed(
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler(
target_thread_id, params,
target_thread_token, params,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
[&profile, &sampling_thread_completed](Profile result_profile) {
BindLambdaForTesting([&profile, &sampling_thread_completed](
Profile result_profile) {
profile = std::move(result_profile);
sampling_thread_completed.Signal();
})));
......@@ -1321,17 +1341,19 @@ PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStop) {
UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
Profile profile;
WithTargetThread(&scenario, BindLambdaForTesting([&](PlatformThreadId
target_thread_id) {
WithTargetThread(
&scenario,
BindLambdaForTesting(
[&](SamplingProfilerThreadToken target_thread_token) {
WaitableEvent sampling_thread_completed(
WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);
StackSamplingProfiler profiler(
target_thread_id, params,
target_thread_token, params,
std::make_unique<TestProfileBuilder>(
module_cache(),
BindLambdaForTesting(
[&profile, &sampling_thread_completed](Profile result_profile) {
BindLambdaForTesting([&profile, &sampling_thread_completed](
Profile result_profile) {
profile = std::move(result_profile);
sampling_thread_completed.Signal();
})));
......
......@@ -59,10 +59,11 @@ bool SuspendableThreadDelegateMac::ScopedSuspendThread::WasSuccessful() const {
// SuspendableThreadDelegateMac -----------------------------------------------
SuspendableThreadDelegateMac::SuspendableThreadDelegateMac(
mach_port_t thread_port)
: thread_port_(thread_port),
thread_stack_base_address_(reinterpret_cast<uintptr_t>(
pthread_get_stackaddr_np(pthread_from_mach_thread_np(thread_port)))) {
SamplingProfilerThreadToken thread_token)
: thread_port_(thread_token.id),
thread_stack_base_address_(
reinterpret_cast<uintptr_t>(pthread_get_stackaddr_np(
pthread_from_mach_thread_np(thread_token.id)))) {
// This class suspends threads, and those threads might be suspended in dyld.
// Therefore, for all the system functions that might be linked in dynamically
// that are used while threads are suspended, make calls to them to make sure
......
......@@ -9,6 +9,7 @@
#include "base/base_export.h"
#include "base/profiler/native_unwinder_mac.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/suspendable_thread_delegate.h"
#include "base/sampling_heap_profiler/module_cache.h"
#include "base/threading/platform_thread.h"
......@@ -35,7 +36,7 @@ class BASE_EXPORT SuspendableThreadDelegateMac
mach_port_t thread_port_;
};
SuspendableThreadDelegateMac(mach_port_t thread_port);
SuspendableThreadDelegateMac(SamplingProfilerThreadToken thread_token);
~SuspendableThreadDelegateMac() override;
SuspendableThreadDelegateMac(const SuspendableThreadDelegateMac&) = delete;
......
......@@ -172,9 +172,9 @@ bool SuspendableThreadDelegateWin::ScopedSuspendThread::WasSuccessful() const {
// ----------------------------------------------------------
SuspendableThreadDelegateWin::SuspendableThreadDelegateWin(
PlatformThreadId thread_id)
: thread_id_(thread_id),
thread_handle_(GetThreadHandle(thread_id)),
SamplingProfilerThreadToken thread_token)
: thread_id_(thread_token.id),
thread_handle_(GetThreadHandle(thread_token.id)),
thread_stack_base_address_(reinterpret_cast<uintptr_t>(
GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase)) {}
......
......@@ -8,6 +8,7 @@
#include <windows.h>
#include "base/base_export.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/suspendable_thread_delegate.h"
#include "base/threading/platform_thread.h"
#include "base/win/scoped_handle.h"
......@@ -34,7 +35,8 @@ class BASE_EXPORT SuspendableThreadDelegateWin
DISALLOW_COPY_AND_ASSIGN(ScopedSuspendThread);
};
explicit SuspendableThreadDelegateWin(PlatformThreadId thread_id);
explicit SuspendableThreadDelegateWin(
SamplingProfilerThreadToken thread_token);
~SuspendableThreadDelegateWin() override;
SuspendableThreadDelegateWin(const SuspendableThreadDelegateWin&) = delete;
......
......@@ -12,9 +12,9 @@ namespace base {
namespace {
uintptr_t GetThreadStackBaseAddress(PlatformThreadId thread_id) {
uintptr_t GetThreadStackBaseAddress(pthread_t pthread_id) {
pthread_attr_t attr;
pthread_getattr_np(thread_id, &attr);
pthread_getattr_np(pthread_id, &attr);
void* base_address;
size_t size;
pthread_attr_getstack(&attr, &base_address, &size);
......@@ -23,9 +23,11 @@ uintptr_t GetThreadStackBaseAddress(PlatformThreadId thread_id) {
} // namespace
ThreadDelegatePosix::ThreadDelegatePosix(PlatformThreadId thread_id)
: thread_id_(thread_id),
thread_stack_base_address_(GetThreadStackBaseAddress(thread_id)) {}
ThreadDelegatePosix::ThreadDelegatePosix(
SamplingProfilerThreadToken thread_token)
: thread_id_(thread_token.id),
thread_stack_base_address_(
GetThreadStackBaseAddress(thread_token.pthread_id)) {}
PlatformThreadId ThreadDelegatePosix::GetThreadId() const {
return thread_id_;
......
......@@ -6,6 +6,7 @@
#define BASE_PROFILER_THREAD_DELEGATE_POSIX_H_
#include "base/base_export.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/thread_delegate.h"
#include "base/threading/platform_thread.h"
......@@ -15,7 +16,7 @@ namespace base {
// POSIX.
class BASE_EXPORT ThreadDelegatePosix : public ThreadDelegate {
public:
ThreadDelegatePosix(PlatformThreadId thread_id);
ThreadDelegatePosix(SamplingProfilerThreadToken thread_token);
ThreadDelegatePosix(const ThreadDelegatePosix&) = delete;
ThreadDelegatePosix& operator=(const ThreadDelegatePosix&) = delete;
......
......@@ -12,6 +12,7 @@
#include "base/message_loop/work_id_provider.h"
#include "base/no_destructor.h"
#include "base/profiler/sample_metadata.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/rand_util.h"
#include "base/threading/platform_thread.h"
#include "base/threading/sequence_local_storage_slot.h"
......@@ -237,7 +238,7 @@ ThreadProfiler::ThreadProfiler(
return;
startup_profiler_ = std::make_unique<StackSamplingProfiler>(
base::PlatformThread::CurrentId(), kSamplingParams,
base::GetSamplingProfilerCurrentThreadToken(), kSamplingParams,
std::make_unique<CallStackProfileBuilder>(
CallStackProfileParams(GetProcess(), thread,
CallStackProfileParams::PROCESS_STARTUP),
......@@ -297,7 +298,7 @@ void ThreadProfiler::StartPeriodicSamplingCollection() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// NB: Destroys the previous profiler as side effect.
periodic_profiler_ = std::make_unique<StackSamplingProfiler>(
base::PlatformThread::CurrentId(), kSamplingParams,
base::GetSamplingProfilerCurrentThreadToken(), kSamplingParams,
std::make_unique<CallStackProfileBuilder>(
CallStackProfileParams(GetProcess(), thread_,
CallStackProfileParams::PERIODIC_COLLECTION),
......
......@@ -13,9 +13,10 @@ namespace {
constexpr size_t kMaxFrameDepth = 48;
} // namespace
StackSamplerAndroid::StackSamplerAndroid(base::PlatformThreadId tid,
StackSamplerAndroid::StackSamplerAndroid(
base::SamplingProfilerThreadToken thread_token,
base::ModuleCache* module_cache)
: tid_(tid), module_cache_(module_cache) {}
: thread_token_(thread_token), module_cache_(module_cache) {}
StackSamplerAndroid::~StackSamplerAndroid() = default;
......@@ -35,7 +36,8 @@ void StackSamplerAndroid::RecordStackFrames(
unwinder_.Initialize();
}
const void* pcs[kMaxFrameDepth];
size_t depth = unwinder_.TraceStack(tid_, stack_buffer, pcs, kMaxFrameDepth);
size_t depth =
unwinder_.TraceStack(thread_token_.id, stack_buffer, pcs, kMaxFrameDepth);
std::vector<base::Frame> frames;
frames.reserve(depth);
for (size_t i = 0; i < depth; ++i) {
......
......@@ -5,6 +5,7 @@
#ifndef SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_STACK_SAMPLER_ANDROID_H_
#define SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_STACK_SAMPLER_ANDROID_H_
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampler.h"
#include "base/sampling_heap_profiler/module_cache.h"
#include "base/threading/platform_thread.h"
......@@ -19,7 +20,7 @@ class StackSamplerAndroid : public base::StackSampler {
// StackUnwinderAndroid only supports sampling one thread at a time. So, the
// clients of this class must ensure synchronization between multiple
// instances of the sampler.
explicit StackSamplerAndroid(base::PlatformThreadId thread_id,
explicit StackSamplerAndroid(base::SamplingProfilerThreadToken thread_token,
base::ModuleCache*);
~StackSamplerAndroid() override;
......@@ -32,7 +33,7 @@ class StackSamplerAndroid : public base::StackSampler {
base::ProfileBuilder* profile_builder) override;
private:
base::PlatformThreadId tid_;
base::SamplingProfilerThreadToken thread_token_;
base::ModuleCache* module_cache_;
StackUnwinderAndroid unwinder_;
};
......
......@@ -13,6 +13,7 @@
#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "base/strings/strcat.h"
#include "base/task/thread_pool/thread_pool_instance.h"
......@@ -461,7 +462,7 @@ TracingSamplerProfiler::TracingProfileBuilder::GetCallstackIDAndMaybeEmit(
std::unique_ptr<TracingSamplerProfiler>
TracingSamplerProfiler::CreateOnMainThread() {
return std::make_unique<TracingSamplerProfiler>(
(base::PlatformThread::CurrentId()));
base::GetSamplingProfilerCurrentThreadToken());
}
// static
......@@ -471,7 +472,7 @@ void TracingSamplerProfiler::CreateOnChildThread() {
return;
auto* profiler =
new TracingSamplerProfiler(base::PlatformThread::CurrentId());
new TracingSamplerProfiler(base::GetSamplingProfilerCurrentThreadToken());
slot->Set(profiler);
}
......@@ -508,9 +509,9 @@ void TracingSamplerProfiler::StopTracingForTesting() {
}
TracingSamplerProfiler::TracingSamplerProfiler(
base::PlatformThreadId sampled_thread_id)
: sampled_thread_id_(sampled_thread_id) {
DCHECK_NE(sampled_thread_id_, base::kInvalidThreadId);
base::SamplingProfilerThreadToken sampled_thread_token)
: sampled_thread_token_(sampled_thread_token) {
DCHECK_NE(sampled_thread_token_.id, base::kInvalidThreadId);
TracingSamplerProfilerDataSource::Get()->RegisterProfiler(this);
}
......@@ -545,20 +546,22 @@ void TracingSamplerProfiler::StartTracing(
params.keep_consistent_sampling_interval = false;
auto profile_builder = std::make_unique<TracingProfileBuilder>(
sampled_thread_id_, std::move(trace_writer), should_enable_filtering);
sampled_thread_token_.id, std::move(trace_writer),
should_enable_filtering);
profile_builder_ = profile_builder.get();
// Create and start the stack sampling profiler.
#if defined(OS_ANDROID)
#if BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
auto* module_cache = profile_builder->GetModuleCache();
profiler_ = std::make_unique<base::StackSamplingProfiler>(
sampled_thread_id_, params, std::move(profile_builder),
std::make_unique<StackSamplerAndroid>(sampled_thread_id_, module_cache));
sampled_thread_token_, params, std::move(profile_builder),
std::make_unique<StackSamplerAndroid>(sampled_thread_token_,
module_cache));
profiler_->Start();
#endif // BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
#else // defined(OS_ANDROID)
profiler_ = std::make_unique<base::StackSamplingProfiler>(
sampled_thread_id_, params, std::move(profile_builder));
sampled_thread_token_, params, std::move(profile_builder));
profiler_->Start();
#endif // defined(OS_ANDROID)
}
......
......@@ -13,6 +13,7 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "base/sequence_checker.h"
#include "base/threading/platform_thread.h"
......@@ -116,7 +117,8 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
static void StartTracingForTesting(tracing::PerfettoProducer* producer);
static void StopTracingForTesting();
explicit TracingSamplerProfiler(base::PlatformThreadId sampled_thread_id);
explicit TracingSamplerProfiler(
base::SamplingProfilerThreadToken sampled_thread_token);
virtual ~TracingSamplerProfiler();
void StartTracing(std::unique_ptr<perfetto::TraceWriter> trace_writer,
......@@ -124,7 +126,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
void StopTracing();
private:
const base::PlatformThreadId sampled_thread_id_;
const base::SamplingProfilerThreadToken sampled_thread_token_;
base::Lock lock_;
std::unique_ptr<base::StackSamplingProfiler> profiler_; // under |lock_|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment