Chromium Code Reviews| Index: base/profiler/stack_sampling_profiler.cc |
| diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc |
| index e25440f80c56b32896b0f018b38e2514086f933d..36474a491548be71a82725637516649fa8be4a95 100644 |
| --- a/base/profiler/stack_sampling_profiler.cc |
| +++ b/base/profiler/stack_sampling_profiler.cc |
| @@ -82,6 +82,22 @@ void AsyncRunner::RunCallbackAndDeleteInstance( |
| task_runner->DeleteSoon(FROM_HERE, object_to_be_deleted.release()); |
| } |
| +void ChangeAtomicFlags(subtle::Atomic32* flags, |
| + subtle::Atomic32 set, |
| + subtle::Atomic32 clear) { |
| + DCHECK(set != 0 || clear != 0); |
| + DCHECK_EQ(0, set & clear); |
| + |
| + subtle::Atomic32 bits = subtle::NoBarrier_Load(flags); |
| + while (true) { |
| + subtle::Atomic32 existing = |
| + subtle::NoBarrier_CompareAndSwap(flags, bits, (bits | set) & ~clear); |
| + if (existing == bits) |
| + break; |
| + bits = existing; |
| + } |
| +} |
| + |
| } // namespace |
| // StackSamplingProfiler::Module ---------------------------------------------- |
| @@ -106,6 +122,21 @@ StackSamplingProfiler::Frame::Frame() |
| : instruction_pointer(0), module_index(kUnknownModuleIndex) { |
| } |
| +// StackSamplingProfiler::Sample ---------------------------------------------- |
| + |
| +StackSamplingProfiler::Sample::Sample() {} |
| + |
| +StackSamplingProfiler::Sample::Sample(const Sample& sample) = default; |
| + |
| +StackSamplingProfiler::Sample::~Sample() {} |
| + |
| +StackSamplingProfiler::Sample::Sample(const Frame& frame) { |
| + frames.push_back(std::move(frame)); |
| +} |
| + |
| +StackSamplingProfiler::Sample::Sample(const std::vector<Frame>& frames) |
| + : frames(frames) {} |
| + |
| // StackSamplingProfiler::CallStackProfile ------------------------------------ |
| StackSamplingProfiler::CallStackProfile::CallStackProfile() {} |
| @@ -184,7 +215,8 @@ void StackSamplingProfiler::SamplingThread::CollectProfile( |
| } |
| ElapsedTimer sample_timer; |
| profile->samples.push_back(Sample()); |
| - native_sampler_->RecordStackSample(&profile->samples.back()); |
| + Sample& sample = profile->samples.back(); |
| + native_sampler_->RecordStackSample(&sample); |
|
Alexei Svitkine (slow)
2016/11/16 19:10:23
Nit: Remove this change since it doesn't seem nece
bcwhite
2016/11/16 23:10:48
Done.
|
| previous_elapsed_sample_time = sample_timer.Elapsed(); |
| } |
| @@ -229,6 +261,8 @@ void StackSamplingProfiler::SamplingThread::Stop() { |
| // StackSamplingProfiler ------------------------------------------------------ |
| +subtle::Atomic32 StackSamplingProfiler::process_phases_ = 0; |
| + |
| StackSamplingProfiler::SamplingParams::SamplingParams() |
| : initial_delay(TimeDelta::FromMilliseconds(0)), |
| bursts(1), |
| @@ -272,7 +306,8 @@ void StackSamplingProfiler::Start() { |
| return; |
| std::unique_ptr<NativeStackSampler> native_sampler = |
| - NativeStackSampler::Create(thread_id_, test_delegate_); |
| + NativeStackSampler::Create(thread_id_, &RecordAnnotations, |
| + test_delegate_); |
| if (!native_sampler) |
| return; |
| @@ -288,6 +323,27 @@ void StackSamplingProfiler::Stop() { |
| sampling_thread_->Stop(); |
| } |
| +// static |
| +void StackSamplingProfiler::SetProcessPhase(int phase) { |
| + DCHECK_LE(0, phase); |
| + DCHECK_GT(static_cast<int>(sizeof(process_phases_) * 8), phase); |
| + DCHECK_EQ(0, subtle::NoBarrier_Load(&process_phases_) & (1 << phase)); |
| + ChangeAtomicFlags(&process_phases_, 1 << phase, 0); |
| +} |
| + |
| +// static |
| +void StackSamplingProfiler::ResetAnnotationsForTesting() { |
| + subtle::NoBarrier_Store(&process_phases_, 0u); |
| +} |
| + |
| +// The code inside this method must not do anything that could acquire a mutex, |
|
Alexei Svitkine (slow)
2016/11/16 19:10:24
Nit: Move this comment inside the method.
bcwhite
2016/11/16 23:10:48
Done.
|
| +// including allocating memory (which includes LOG messages) because that mutex |
| +// could be held by a stopped thread, thus resulting in deadlock. |
| +// static |
| +void StackSamplingProfiler::RecordAnnotations(Sample* sample) { |
| + sample->process_phases = subtle::NoBarrier_Load(&process_phases_); |
| +} |
| + |
| // StackSamplingProfiler::Frame global functions ------------------------------ |
| bool operator==(const StackSamplingProfiler::Module& a, |
| @@ -296,6 +352,26 @@ bool operator==(const StackSamplingProfiler::Module& a, |
| a.filename == b.filename; |
| } |
| +bool operator==(const StackSamplingProfiler::Sample& a, |
| + const StackSamplingProfiler::Sample& b) { |
| + return a.process_phases == b.process_phases && a.frames == b.frames; |
| +} |
| + |
| +bool operator!=(const StackSamplingProfiler::Sample& a, |
| + const StackSamplingProfiler::Sample& b) { |
| + return !(a == b); |
| +} |
| + |
| +bool operator<(const StackSamplingProfiler::Sample& a, |
| + const StackSamplingProfiler::Sample& b) { |
| + if (a.process_phases < b.process_phases) |
| + return true; |
| + if (a.process_phases > b.process_phases) |
| + return false; |
| + |
| + return a.frames < b.frames; |
| +} |
| + |
| bool operator==(const StackSamplingProfiler::Frame &a, |
| const StackSamplingProfiler::Frame &b) { |
| return a.instruction_pointer == b.instruction_pointer && |