diff options
author | georgesak <georgesak@chromium.org> | 2015-08-14 08:52:37 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-14 15:53:20 +0000 |
commit | 3bd527974c0cea7b1e0e9965fa9e13823861ebb6 (patch) | |
tree | 3e10e76d3200b25b4fb65821d9c6411b5962d97a /base | |
parent | 225925531da365c5ca1e083ed14188621dbb9139 (diff) | |
download | chromium_src-3bd527974c0cea7b1e0e9965fa9e13823861ebb6.zip chromium_src-3bd527974c0cea7b1e0e9965fa9e13823861ebb6.tar.gz chromium_src-3bd527974c0cea7b1e0e9965fa9e13823861ebb6.tar.bz2 |
[ETW Export] Add polling for ETW keyword.
This adds a background low-priority thread for each process that monitors the keyword and adjusts the categories accordingly. This allows users to start profiling (using UIForETW or Xpef directly) and specify which categories to enable, without having to restart Chrome.
Notes:
- TraceEventETWExport is a friend of TraceLog (see comment in code).
- ETW exporting still needs to be enabled using the command line or in about:flags.
BUG=491909
Review URL: https://codereview.chromium.org/1279353002
Cr-Commit-Position: refs/heads/master@{#343393}
Diffstat (limited to 'base')
-rw-r--r-- | base/trace_event/trace_event_etw_export_win.cc | 72 | ||||
-rw-r--r-- | base/trace_event/trace_event_etw_export_win.h | 15 | ||||
-rw-r--r-- | base/trace_event/trace_log.cc | 19 | ||||
-rw-r--r-- | base/trace_event/trace_log.h | 7 |
4 files changed, 101 insertions, 12 deletions
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc index e61a7b2..00cc8c2 100644 --- a/base/trace_event/trace_event_etw_export_win.cc +++ b/base/trace_event/trace_event_etw_export_win.cc @@ -9,6 +9,7 @@ #include "base/memory/singleton.h" #include "base/strings/string_tokenizer.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/platform_thread.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_impl.h" @@ -90,6 +91,30 @@ const char* disabled_other_events_group_name = "__DISABLED_OTHER_EVENTS"; // 0x4000000000000000 uint64 other_events_keyword_bit = 1ULL << 61; uint64 disabled_other_events_keyword_bit = 1ULL << 62; + +// This object will be created by each process. It's a background (low-priority) +// thread that will monitor the ETW keyword for any changes. +class ETWKeywordUpdateThread : public base::PlatformThread::Delegate { + public: + ETWKeywordUpdateThread() {} + ~ETWKeywordUpdateThread() override {} + + // Implementation of PlatformThread::Delegate: + void ThreadMain() override { + base::PlatformThread::SetName("ETW Keyword Update Thread"); + base::TimeDelta sleep_time = + base::TimeDelta::FromMilliseconds(kUpdateTimerDelayMs); + while (1) { + base::PlatformThread::Sleep(sleep_time); + base::trace_event::TraceEventETWExport::UpdateETWKeyword(); + } + } + + private: + // Time between checks for ETW keyword changes (in milliseconds). + unsigned int kUpdateTimerDelayMs = 1000; +}; + } // namespace // Redirector function for EventRegister. Called by macros in @@ -143,8 +168,6 @@ TraceEventETWExport::TraceEventETWExport() // Register the ETW provider. If registration fails then the event logging // calls will fail (on XP this call will do nothing). EventRegisterChrome(); - - UpdateEnabledCategories(); } } @@ -160,19 +183,33 @@ TraceEventETWExport* TraceEventETWExport::GetInstance() { // static void TraceEventETWExport::EnableETWExport() { - if (GetInstance()) - GetInstance()->etw_export_enabled_ = true; + auto* instance = GetInstance(); + if (instance && !instance->etw_export_enabled_) { + instance->etw_export_enabled_ = true; + // Sync the enabled categories with ETW by calling UpdateEnabledCategories() + // that checks the keyword. Then create a thread that will call that same + // function periodically, to make sure we stay in sync. + instance->UpdateEnabledCategories(); + if (instance->keyword_update_thread_handle_.is_null()) { + instance->keyword_update_thread_.reset(new ETWKeywordUpdateThread); + PlatformThread::CreateWithPriority( + 0, instance->keyword_update_thread_.get(), + &instance->keyword_update_thread_handle_, ThreadPriority::BACKGROUND); + } + } } // static void TraceEventETWExport::DisableETWExport() { - if (GetInstance()) - GetInstance()->etw_export_enabled_ = false; + auto* instance = GetInstance(); + if (instance && instance->etw_export_enabled_) + instance->etw_export_enabled_ = false; } // static bool TraceEventETWExport::IsETWExportEnabled() { - return (GetInstance() && GetInstance()->etw_export_enabled_); + auto* instance = GetInstance(); + return (instance && instance->etw_export_enabled_); } // static @@ -187,8 +224,8 @@ void TraceEventETWExport::AddEvent( const unsigned long long* arg_values, const scoped_refptr<ConvertableToTraceFormat>* convertable_values) { // We bail early in case exporting is disabled or no consumer is listening. - if (!GetInstance() || !GetInstance()->etw_export_enabled_ || - !EventEnabledChromeEvent()) + auto* instance = GetInstance(); + if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) return; const char* phase_string = nullptr; @@ -294,8 +331,8 @@ void TraceEventETWExport::AddCustomEvent(const char* name, const char* arg_value_2, const char* arg_name_3, const char* arg_value_3) { - if (!GetInstance() || !GetInstance()->etw_export_enabled_ || - !EventEnabledChromeEvent()) + auto* instance = GetInstance(); + if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) return; EventWriteChromeEvent(name, phase, arg_name_1, arg_value_1, arg_name_2, @@ -306,7 +343,7 @@ void TraceEventETWExport::AddCustomEvent(const char* name, bool TraceEventETWExport::IsCategoryGroupEnabled( const char* category_group_name) { DCHECK(category_group_name); - auto instance = GetInstance(); + auto* instance = GetInstance(); if (instance == nullptr) return false; @@ -354,6 +391,9 @@ bool TraceEventETWExport::UpdateEnabledCategories() { categories_status_[disabled_other_events_group_name] = false; } + // Update the categories in TraceLog. + TraceLog::GetInstance()->UpdateETWCategoryGroupEnabledFlags(); + return true; } @@ -376,5 +416,13 @@ bool TraceEventETWExport::IsCategoryEnabled(const char* category_name) const { } } +// static +void TraceEventETWExport::UpdateETWKeyword() { + if (!IsETWExportEnabled()) + return; + auto* instance = GetInstance(); + DCHECK(instance); + instance->UpdateEnabledCategories(); +} } // namespace trace_event } // namespace base diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h index 9f73d78..523c44b 100644 --- a/base/trace_event/trace_event_etw_export_win.h +++ b/base/trace_event/trace_event_etw_export_win.h @@ -16,6 +16,10 @@ template <typename Type> struct StaticMemorySingletonTraits; +namespace { +class ETWKeywordUpdateThread; +} + namespace base { namespace trace_event { @@ -67,6 +71,8 @@ class BASE_EXPORT TraceEventETWExport { private: // Ensure only the provider can construct us. friend struct StaticMemorySingletonTraits<TraceEventETWExport>; + // To have access to UpdateKeyword(). + friend class ETWKeywordUpdateThread; TraceEventETWExport(); // Updates the list of enabled categories by consulting the ETW keyword. @@ -76,6 +82,10 @@ class BASE_EXPORT TraceEventETWExport { // Returns true if the category is enabled. bool IsCategoryEnabled(const char* category_name) const; + // Called back by the update thread to check for potential changes to the + // keyword. + static void UpdateETWKeyword(); + // True if ETW is enabled. Allows hiding the exporting behind a flag. bool etw_export_enabled_; @@ -85,6 +95,11 @@ class BASE_EXPORT TraceEventETWExport { // Local copy of the ETW keyword. uint64 etw_match_any_keyword_; + // Background thread that monitors changes to the ETW keyword and updates + // the enabled categories when a change occurs. + scoped_ptr<ETWKeywordUpdateThread> keyword_update_thread_; + PlatformThreadHandle keyword_update_thread_handle_; + DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport); }; diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 8eb46c5..af2124e 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc @@ -1707,6 +1707,25 @@ TraceBuffer* TraceLog::CreateTraceBuffer() { kTraceEventVectorBufferChunks); } +#if defined(OS_WIN) +void TraceLog::UpdateETWCategoryGroupEnabledFlags() { + AutoLock lock(lock_); + size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); + // Go through each category and set/clear the ETW bit depending on whether the + // category is enabled. + for (size_t i = 0; i < category_index; i++) { + const char* category_group = g_category_groups[i]; + DCHECK(category_group); + if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( + category_group)) { + g_category_group_enabled[category_index] |= ENABLED_FOR_ETW_EXPORT; + } else { + g_category_group_enabled[category_index] &= ~ENABLED_FOR_ETW_EXPORT; + } + } +} +#endif // defined(OS_WIN) + void ConvertableToTraceFormat::EstimateTraceMemoryOverhead( TraceEventMemoryOverhead* overhead) { overhead->Add("ConvertableToTraceFormat(Unknown)", sizeof(*this)); diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index 510113a..dedebce 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h @@ -307,6 +307,13 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { // may not handle the flush request in time causing lost of unflushed events. void SetCurrentThreadBlocksMessageLoop(); +#if defined(OS_WIN) + // This function is called by the ETW exporting module whenever the ETW + // keyword (flags) changes. This keyword indicates which categories should be + // exported, so whenever it changes, we adjust accordingly. + void UpdateETWCategoryGroupEnabledFlags(); +#endif + private: typedef unsigned int InternalTraceOptions; |