Commit b42bfa41 authored by Daniel Libby's avatar Daniel Libby Committed by Commit Bot

Remove ETW update thread

Wrap the callback that notifies of changes instead and trigger updates
off of that. Remove the notion of Disabling the ETW exporter itself,
instead just use whether the provider is enabled or not.

Leave the flag for now and continue to conditionally enable. Follow
up change will remove the flag and always have the ability to export
trace events to ETW.

Bug: 781991
Change-Id: Ifb0d3c5669fca255ca4c0bcd9f84e4034995761b
Reviewed-on: https://chromium-review.googlesource.com/c/1423559Reviewed-by: default avatarBruce Dawson <brucedawson@chromium.org>
Reviewed-by: default avatarPrimiano Tucci <primiano@chromium.org>
Commit-Queue: Daniel Libby <dlibby@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#626235}
parent 41e0f7d7
......@@ -86,40 +86,39 @@ const uint64_t kOtherEventsKeywordBit = 1ULL << 61;
const uint64_t kDisabledOtherEventsKeywordBit = 1ULL << 62;
const size_t kNumberOfCategories = ARRAYSIZE(kFilteredEventGroupNames) + 2U;
static void __stdcall EtwEnableCallback(LPCGUID SourceId,
ULONG ControlCode,
UCHAR Level,
ULONGLONG MatchAnyKeyword,
ULONGLONG MatchAllKeyword,
PEVENT_FILTER_DESCRIPTOR FilterData,
PVOID CallbackContext) {
// Invoke the default callback, which updates the information inside
// CHROME_Context.
McGenControlCallbackV2(SourceId, ControlCode, Level, MatchAnyKeyword,
MatchAllKeyword, FilterData, CallbackContext);
base::trace_event::TraceEventETWExport::OnETWEnableUpdate();
}
} // namespace
namespace base {
namespace trace_event {
// 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 TraceEventETWExport::ETWKeywordUpdateThread
: public PlatformThread::Delegate {
public:
ETWKeywordUpdateThread() {}
~ETWKeywordUpdateThread() override {}
// Implementation of PlatformThread::Delegate:
void ThreadMain() override {
PlatformThread::SetName("ETW Keyword Update Thread");
TimeDelta sleep_time = TimeDelta::FromMilliseconds(kUpdateTimerDelayMs);
while (1) {
PlatformThread::Sleep(sleep_time);
trace_event::TraceEventETWExport::UpdateETWKeyword();
}
}
private:
// Time between checks for ETW keyword changes (in milliseconds).
unsigned int kUpdateTimerDelayMs = 1000;
};
bool TraceEventETWExport::is_registration_complete_ = false;
TraceEventETWExport::TraceEventETWExport()
: etw_export_enabled_(false), etw_match_any_keyword_(0ULL) {
TraceEventETWExport::TraceEventETWExport() : etw_match_any_keyword_(0ULL) {
// Register the ETW provider. If registration fails then the event logging
// calls will fail.
EventRegisterChrome();
// calls will fail. We're essentially doing the same operation as
// EventRegisterChrome (which was auto generated for our provider by the
// ETW manifest compiler), but instead we're passing our own callback.
// This allows us to detect changes to enable/disable/keyword changes.
// ChromeHandle and the other parameters to EventRegister are all generated
// globals from chrome_events_win.h
DCHECK(!ChromeHandle);
EventRegister(&CHROME, &EtwEnableCallback, &CHROME_Context, &ChromeHandle);
TraceEventETWExport::is_registration_complete_ = true;
// Make sure to initialize the map with all the group names. Subsequent
// modifications will be made by the background thread and only affect the
......@@ -134,39 +133,20 @@ TraceEventETWExport::TraceEventETWExport()
TraceEventETWExport::~TraceEventETWExport() {
EventUnregisterChrome();
is_registration_complete_ = false;
}
// static
void TraceEventETWExport::EnableETWExport() {
auto* instance = GetInstance();
if (instance && !instance->etw_export_enabled_) {
instance->etw_export_enabled_ = true;
if (instance) {
// 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.
// that checks the keyword. We'll stay in sync via the EtwEnableCallback
// we register in TraceEventETWExport's constructor.
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() {
auto* instance = GetInstance();
if (instance && instance->etw_export_enabled_)
instance->etw_export_enabled_ = false;
}
// static
bool TraceEventETWExport::IsETWExportEnabled() {
auto* instance = GetInstanceIfExists();
return (instance && instance->etw_export_enabled_);
}
// static
void TraceEventETWExport::AddEvent(char phase,
const unsigned char* category_group_enabled,
......@@ -175,7 +155,7 @@ void TraceEventETWExport::AddEvent(char phase,
const TraceArguments* args) {
// We bail early in case exporting is disabled or no consumer is listening.
auto* instance = GetInstance();
if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
if (!instance || !EventEnabledChromeEvent())
return;
const char* phase_string = nullptr;
......@@ -271,7 +251,7 @@ void TraceEventETWExport::AddEvent(char phase,
// static
void TraceEventETWExport::AddCompleteEndEvent(const char* name) {
auto* instance = GetInstance();
if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
if (!instance || !EventEnabledChromeEvent())
return;
EventWriteChromeEvent(name, "Complete End", "", "", "", "", "", "");
......@@ -285,7 +265,7 @@ bool TraceEventETWExport::IsCategoryGroupEnabled(
if (instance == nullptr)
return false;
if (!instance->IsETWExportEnabled())
if (!EventEnabledChromeEvent())
return false;
CStringTokenizer category_group_tokens(category_group_name.begin(),
......@@ -357,12 +337,16 @@ bool TraceEventETWExport::IsCategoryEnabled(StringPiece category_name) const {
}
// static
void TraceEventETWExport::UpdateETWKeyword() {
if (!IsETWExportEnabled())
return;
void TraceEventETWExport::OnETWEnableUpdate() {
// During construction, if tracing is already enabled, we'll get
// a callback synchronously on the same thread. Calling GetInstance
// in that case will hang since we're in the process of creating the
// singleton.
if (is_registration_complete_) {
auto* instance = GetInstance();
DCHECK(instance);
if (instance)
instance->UpdateEnabledCategories();
}
}
// static
......
......@@ -36,14 +36,9 @@ class BASE_EXPORT TraceEventETWExport {
// post-AtExit processing.
static TraceEventETWExport* GetInstanceIfExists();
// Enables/disables exporting of events to ETW. If disabled,
// AddEvent and AddCustomEvent will simply return when called.
// Enables exporting of events to ETW. If tracing is disabled for the Chrome
// provider, AddEvent and AddCustomEvent will simply return when called.
static void EnableETWExport();
static void DisableETWExport();
// Returns true if ETW is enabled. For now, this is true if the command line
// flag is specified.
static bool IsETWExportEnabled();
// Exports an event to ETW. This is mainly used in
// TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
......@@ -59,12 +54,14 @@ class BASE_EXPORT TraceEventETWExport {
// Returns true if any category in the group is enabled.
static bool IsCategoryGroupEnabled(StringPiece category_group_name);
// Called from the ETW EnableCallback when the state of the provider or
// keywords has changed.
static void OnETWEnableUpdate();
private:
// Ensure only the provider can construct us.
friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
// To have access to UpdateKeyword().
class ETWKeywordUpdateThread;
TraceEventETWExport();
// Updates the list of enabled categories by consulting the ETW keyword.
......@@ -74,12 +71,7 @@ class BASE_EXPORT TraceEventETWExport {
// Returns true if the category is enabled.
bool IsCategoryEnabled(StringPiece 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_;
static bool is_registration_complete_;
// Maps category names to their status (enabled/disabled).
std::map<StringPiece, bool> categories_status_;
......@@ -87,11 +79,6 @@ class BASE_EXPORT TraceEventETWExport {
// Local copy of the ETW keyword.
uint64_t etw_match_any_keyword_;
// Background thread that monitors changes to the ETW keyword and updates
// the enabled categories when a change occurs.
std::unique_ptr<ETWKeywordUpdateThread> keyword_update_thread_;
PlatformThreadHandle keyword_update_thread_handle_;
DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
};
......
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