From fcf1bac99a6277234d35797847a01dfdb1f86f7a Mon Sep 17 00:00:00 2001 From: alph Date: Tue, 27 Sep 2016 13:12:41 -0700 Subject: [PATCH] [tracing] Implement Add/RemoveTraceStateObserver for default platform. BUG=chromium:406277 Review-Url: https://codereview.chromium.org/2369073003 Cr-Commit-Position: refs/heads/master@{#39794} --- include/libplatform/v8-tracing.h | 14 ++++- src/libplatform/default-platform.cc | 24 +++++--- src/libplatform/default-platform.h | 6 +- src/libplatform/tracing/tracing-controller.cc | 43 ++++++++++++- test/cctest/libplatform/test-tracing.cc | 60 +++++++++++++++++++ 5 files changed, 136 insertions(+), 11 deletions(-) diff --git a/include/libplatform/v8-tracing.h b/include/libplatform/v8-tracing.h index bbf1dd71f2..5652568bce 100644 --- a/include/libplatform/v8-tracing.h +++ b/include/libplatform/v8-tracing.h @@ -7,11 +7,17 @@ #include #include +#include #include #include "include/v8-platform.h" namespace v8 { + +namespace base { +class Mutex; +} // namespace base + namespace platform { namespace tracing { @@ -227,7 +233,8 @@ class TracingController { ENABLED_FOR_ETW_EXPORT = 1 << 3 }; - TracingController() {} + TracingController(); + ~TracingController(); void Initialize(TraceBuffer* trace_buffer); const uint8_t* GetCategoryGroupEnabled(const char* category_group); static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); @@ -244,6 +251,9 @@ class TracingController { void StartTracing(TraceConfig* trace_config); void StopTracing(); + void AddTraceStateObserver(Platform::TraceStateObserver* observer); + void RemoveTraceStateObserver(Platform::TraceStateObserver* observer); + private: const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group); void UpdateCategoryGroupEnabledFlag(size_t category_index); @@ -251,6 +261,8 @@ class TracingController { std::unique_ptr trace_buffer_; std::unique_ptr trace_config_; + std::unique_ptr mutex_; + std::unordered_set observers_; Mode mode_ = DISABLED; // Disallow copy and assign diff --git a/src/libplatform/default-platform.cc b/src/libplatform/default-platform.cc index b8319ea3a9..f64143ed24 100644 --- a/src/libplatform/default-platform.cc +++ b/src/libplatform/default-platform.cc @@ -39,9 +39,14 @@ void SetTracingController( const int DefaultPlatform::kMaxThreadPoolSize = 8; DefaultPlatform::DefaultPlatform() - : initialized_(false), thread_pool_size_(0), tracing_controller_(NULL) {} + : initialized_(false), thread_pool_size_(0) {} DefaultPlatform::~DefaultPlatform() { + if (tracing_controller_) { + tracing_controller_->StopTracing(); + tracing_controller_.reset(); + } + base::LockGuard guard(&lock_); queue_.Terminate(); if (initialized_) { @@ -63,11 +68,6 @@ DefaultPlatform::~DefaultPlatform() { i->second.pop(); } } - - if (tracing_controller_) { - tracing_controller_->StopTracing(); - delete tracing_controller_; - } } @@ -219,12 +219,22 @@ const char* DefaultPlatform::GetCategoryGroupName( void DefaultPlatform::SetTracingController( tracing::TracingController* tracing_controller) { - tracing_controller_ = tracing_controller; + tracing_controller_.reset(tracing_controller); } size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() { return static_cast(thread_pool_size_); } +void DefaultPlatform::AddTraceStateObserver(TraceStateObserver* observer) { + if (!tracing_controller_) return; + tracing_controller_->AddTraceStateObserver(observer); +} + +void DefaultPlatform::RemoveTraceStateObserver(TraceStateObserver* observer) { + if (!tracing_controller_) return; + tracing_controller_->RemoveTraceStateObserver(observer); +} + } // namespace platform } // namespace v8 diff --git a/src/libplatform/default-platform.h b/src/libplatform/default-platform.h index 3881fd2d02..dc96289eaa 100644 --- a/src/libplatform/default-platform.h +++ b/src/libplatform/default-platform.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -62,6 +63,9 @@ class DefaultPlatform : public Platform { const char* name, uint64_t handle) override; void SetTracingController(tracing::TracingController* tracing_controller); + void AddTraceStateObserver(TraceStateObserver* observer) override; + void RemoveTraceStateObserver(TraceStateObserver* observer) override; + private: static const int kMaxThreadPoolSize; @@ -80,7 +84,7 @@ class DefaultPlatform : public Platform { std::priority_queue, std::greater > > main_thread_delayed_queue_; - tracing::TracingController* tracing_controller_; + std::unique_ptr tracing_controller_; DISALLOW_COPY_AND_ASSIGN(DefaultPlatform); }; diff --git a/src/libplatform/tracing/tracing-controller.cc b/src/libplatform/tracing/tracing-controller.cc index 92a8515823..c1a4057c05 100644 --- a/src/libplatform/tracing/tracing-controller.cc +++ b/src/libplatform/tracing/tracing-controller.cc @@ -38,8 +38,13 @@ const int g_num_builtin_categories = 4; // Skip default categories. v8::base::AtomicWord g_category_index = g_num_builtin_categories; +TracingController::TracingController() {} + +TracingController::~TracingController() {} + void TracingController::Initialize(TraceBuffer* trace_buffer) { trace_buffer_.reset(trace_buffer); + mutex_.reset(new base::Mutex()); } uint64_t TracingController::AddTraceEvent( @@ -93,13 +98,29 @@ const char* TracingController::GetCategoryGroupName( void TracingController::StartTracing(TraceConfig* trace_config) { trace_config_.reset(trace_config); - mode_ = RECORDING_MODE; - UpdateCategoryGroupEnabledFlags(); + std::unordered_set observers_copy; + { + base::LockGuard lock(mutex_.get()); + mode_ = RECORDING_MODE; + UpdateCategoryGroupEnabledFlags(); + observers_copy = observers_; + } + for (auto o : observers_copy) { + o->OnTraceEnabled(); + } } void TracingController::StopTracing() { mode_ = DISABLED; UpdateCategoryGroupEnabledFlags(); + std::unordered_set observers_copy; + { + base::LockGuard lock(mutex_.get()); + observers_copy = observers_; + } + for (auto o : observers_copy) { + o->OnTraceDisabled(); + } trace_buffer_->Flush(); } @@ -174,6 +195,24 @@ const uint8_t* TracingController::GetCategoryGroupEnabledInternal( return category_group_enabled; } +void TracingController::AddTraceStateObserver( + Platform::TraceStateObserver* observer) { + { + base::LockGuard lock(mutex_.get()); + observers_.insert(observer); + if (mode_ != RECORDING_MODE) return; + } + // Fire the observer if recording is already in progress. + observer->OnTraceEnabled(); +} + +void TracingController::RemoveTraceStateObserver( + Platform::TraceStateObserver* observer) { + base::LockGuard lock(mutex_.get()); + DCHECK(observers_.find(observer) != observers_.end()); + observers_.erase(observer); +} + } // namespace tracing } // namespace platform } // namespace v8 diff --git a/test/cctest/libplatform/test-tracing.cc b/test/cctest/libplatform/test-tracing.cc index b2579cecd5..0ca51c3089 100644 --- a/test/cctest/libplatform/test-tracing.cc +++ b/test/cctest/libplatform/test-tracing.cc @@ -332,6 +332,66 @@ TEST(TestTracingControllerMultipleArgsAndCopy) { i::V8::SetPlatformForTesting(old_platform); } +namespace { + +class TraceStateObserverImpl : public Platform::TraceStateObserver { + public: + void OnTraceEnabled() override { ++enabled_count; } + void OnTraceDisabled() override { ++disabled_count; } + + int enabled_count = 0; + int disabled_count = 0; +}; + +} // namespace + +TEST(TracingObservers) { + v8::Platform* old_platform = i::V8::GetCurrentPlatform(); + v8::Platform* default_platform = v8::platform::CreateDefaultPlatform(); + i::V8::SetPlatformForTesting(default_platform); + + v8::platform::tracing::TracingController tracing_controller; + v8::platform::SetTracingController(default_platform, &tracing_controller); + MockTraceWriter* writer = new MockTraceWriter(); + v8::platform::tracing::TraceBuffer* ring_buffer = + v8::platform::tracing::TraceBuffer::CreateTraceBufferRingBuffer(1, + writer); + tracing_controller.Initialize(ring_buffer); + v8::platform::tracing::TraceConfig* trace_config = + new v8::platform::tracing::TraceConfig(); + trace_config->AddIncludedCategory("v8"); + + TraceStateObserverImpl observer; + default_platform->AddTraceStateObserver(&observer); + + CHECK_EQ(0, observer.enabled_count); + CHECK_EQ(0, observer.disabled_count); + + tracing_controller.StartTracing(trace_config); + + CHECK_EQ(1, observer.enabled_count); + CHECK_EQ(0, observer.disabled_count); + + tracing_controller.StopTracing(); + + CHECK_EQ(1, observer.enabled_count); + CHECK_EQ(1, observer.disabled_count); + + default_platform->RemoveTraceStateObserver(&observer); + + CHECK_EQ(1, observer.enabled_count); + CHECK_EQ(1, observer.disabled_count); + + trace_config = new v8::platform::tracing::TraceConfig(); + tracing_controller.StartTracing(trace_config); + tracing_controller.StopTracing(); + + CHECK_EQ(1, observer.enabled_count); + CHECK_EQ(1, observer.disabled_count); + + i::V8::SetPlatformForTesting(old_platform); +} + } // namespace tracing } // namespace platform } // namespace v8