From c77959ff6858e0fa501e2d29fc447984877943c6 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Thu, 7 Mar 2019 18:34:17 -0800 Subject: [PATCH] Fix how we check whether events are enabled via LTTng (dotnet/coreclr#22707) * Fix how we check whether events are enabled via LTTng * Add GCToEEInterface::UpdateGCEventStatus * Fix build errors * Finished hooking it up to post_gc * Some comments about the event keyword/level detection logic * Fix windows build * Fix Prv provider keyword logic * forgot to add one more ifdef * Fix OSX build * one more ifdef to fix * Addressing PR feedback * Update GCEventStatus at gc_heap::initialize_gc too Commit migrated from https://github.com/dotnet/coreclr/commit/4685a1e008ad7cf4118e8778d89e63d87ca5b7b6 --- src/coreclr/src/gc/env/gcenv.ee.h | 1 + src/coreclr/src/gc/gc.cpp | 13 +++++++++ src/coreclr/src/gc/gcenv.ee.standalone.inl | 8 +++++ src/coreclr/src/gc/gceventstatus.h | 29 +++++++++++------- src/coreclr/src/gc/gcinterface.ee.h | 3 ++ src/coreclr/src/gc/gcinterface.h | 10 +++++++ src/coreclr/src/vm/gcenv.ee.cpp | 47 ++++++++++++++++++++++++++++++ src/coreclr/src/vm/gcenv.ee.h | 15 ++++++++++ 8 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/gc/env/gcenv.ee.h b/src/coreclr/src/gc/env/gcenv.ee.h index ec72517..c91eadb 100644 --- a/src/coreclr/src/gc/env/gcenv.ee.h +++ b/src/coreclr/src/gc/env/gcenv.ee.h @@ -96,6 +96,7 @@ public: static void AnalyzeSurvivorsFinished(int condemnedGeneration); static void VerifySyncTableEntry(); + static void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords); }; #endif // __GCENV_EE_H__ diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index 95fe21c..a26ad8d 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -10192,6 +10192,13 @@ HRESULT gc_heap::initialize_gc (size_t segment_size, yp_spin_count_unit = 32 * g_num_processors; #endif //MULTIPLE_HEAPS +#if defined(__linux__) + GCToEEInterface::UpdateGCEventStatus(static_cast(GCEventStatus::GetEnabledLevel(GCEventProvider_Default)), + static_cast(GCEventStatus::GetEnabledKeywords(GCEventProvider_Default)), + static_cast(GCEventStatus::GetEnabledLevel(GCEventProvider_Private)), + static_cast(GCEventStatus::GetEnabledKeywords(GCEventProvider_Private))); +#endif // __linux__ + if (!init_semi_shared()) { hres = E_FAIL; @@ -35553,6 +35560,12 @@ void gc_heap::do_pre_gc() last_gc_index = VolatileLoad(&settings.gc_index); GCHeap::UpdatePreGCCounters(); +#if defined(__linux__) + GCToEEInterface::UpdateGCEventStatus(static_cast(GCEventStatus::GetEnabledLevel(GCEventProvider_Default)), + static_cast(GCEventStatus::GetEnabledKeywords(GCEventProvider_Default)), + static_cast(GCEventStatus::GetEnabledLevel(GCEventProvider_Private)), + static_cast(GCEventStatus::GetEnabledKeywords(GCEventProvider_Private))); +#endif // __linux__ if (settings.concurrent) { diff --git a/src/coreclr/src/gc/gcenv.ee.standalone.inl b/src/coreclr/src/gc/gcenv.ee.standalone.inl index b000dad..b5c2c76 100644 --- a/src/coreclr/src/gc/gcenv.ee.standalone.inl +++ b/src/coreclr/src/gc/gcenv.ee.standalone.inl @@ -323,4 +323,12 @@ inline void GCToEEInterface::VerifySyncTableEntry() g_theGCToCLR->VerifySyncTableEntry(); } +inline void GCToEEInterface::UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords) +{ + assert(g_theGCToCLR != nullptr); +#if defined(__linux__) + g_theGCToCLR->UpdateGCEventStatus(publicLevel, publicKeywords, privateLevel, privateKeywords); +#endif // __linux__ +} + #endif // __GCTOENV_EE_STANDALONE_INL__ diff --git a/src/coreclr/src/gc/gceventstatus.h b/src/coreclr/src/gc/gceventstatus.h index c49e767..1f31d42 100644 --- a/src/coreclr/src/gc/gceventstatus.h +++ b/src/coreclr/src/gc/gceventstatus.h @@ -32,15 +32,6 @@ // Uncomment this define to print out event state changes to standard error. // #define TRACE_GC_EVENT_STATE 1 -/* - * GCEventProvider represents one of the two providers that the GC can - * fire events from: the default and private providers. - */ -enum GCEventProvider -{ - GCEventProvider_Default = 0, - GCEventProvider_Private = 1 -}; /* * GCEventStatus maintains all eventing state for the GC. It consists @@ -98,6 +89,22 @@ public: #endif // TRACE_GC_EVENT_STATE } + /* + * Returns currently enabled levels + */ + static inline GCEventLevel GetEnabledLevel(GCEventProvider provider) + { + return enabledLevels[static_cast(provider)].LoadWithoutBarrier(); + } + + /* + * Returns currently enabled keywords in GCPublic + */ + static inline GCEventKeyword GetEnabledKeywords(GCEventProvider provider) + { + return enabledKeywords[static_cast(provider)].LoadWithoutBarrier(); + } + #if TRACE_GC_EVENT_STATE private: static void DebugDumpState(GCEventProvider provider) @@ -236,6 +243,7 @@ void FireDynamicEvent(const char* name, EventArgument... arguments) * payload. Known events will delegate to IGCToCLREventSink::Fire##name. */ #if FEATURE_EVENT_TRACE + #define KNOWN_EVENT(name, provider, level, keyword) \ inline bool GCEventEnabled##name() { return GCEventStatus::IsEnabled(provider, keyword, level); } \ template \ @@ -258,7 +266,8 @@ void FireDynamicEvent(const char* name, EventArgument... arguments) #define EVENT_ENABLED(name) GCEventEnabled##name() #define FIRE_EVENT(name, ...) GCEventFire##name(__VA_ARGS__) -#else + +#else // FEATURE_EVENT_TRACE #define EVENT_ENABLED(name) false #define FIRE_EVENT(name, ...) 0 #endif // FEATURE_EVENT_TRACE diff --git a/src/coreclr/src/gc/gcinterface.ee.h b/src/coreclr/src/gc/gcinterface.ee.h index 228bb37..4ce9203 100644 --- a/src/coreclr/src/gc/gcinterface.ee.h +++ b/src/coreclr/src/gc/gcinterface.ee.h @@ -435,6 +435,9 @@ public: virtual void VerifySyncTableEntry() = 0; + + virtual + void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLEvel, int privateKeywords) = 0; }; #endif // _GCINTERFACE_EE_H_ diff --git a/src/coreclr/src/gc/gcinterface.h b/src/coreclr/src/gc/gcinterface.h index 249466a..9744eb0 100644 --- a/src/coreclr/src/gc/gcinterface.h +++ b/src/coreclr/src/gc/gcinterface.h @@ -199,6 +199,16 @@ extern uint8_t* g_GCShadowEnd; extern uint8_t* g_shadow_lowest_address; #endif +/* + * GCEventProvider represents one of the two providers that the GC can + * fire events from: the default and private providers. + */ +enum GCEventProvider +{ + GCEventProvider_Default = 0, + GCEventProvider_Private = 1 +}; + // Event levels corresponding to events that can be fired by the GC. enum GCEventLevel { diff --git a/src/coreclr/src/vm/gcenv.ee.cpp b/src/coreclr/src/vm/gcenv.ee.cpp index f27d3f3..7788022 100644 --- a/src/coreclr/src/vm/gcenv.ee.cpp +++ b/src/coreclr/src/vm/gcenv.ee.cpp @@ -1558,3 +1558,50 @@ void GCToEEInterface::VerifySyncTableEntry() SyncBlockCache::GetSyncBlockCache()->VerifySyncTableEntry(); #endif // VERIFY_HEAP } + +void GCToEEInterface::UpdateGCEventStatus(int currentPublicLevel, int currentPublicKeywords, int currentPrivateLevel, int currentPrivateKeywords) +{ +#if defined(__linux__) + LIMITED_METHOD_CONTRACT; + // LTTng does not have a notion of enabling events via "keyword"/"level" but we have to + // somehow implement a similar behavior to it. + + // To do this, we manaully check for events that are enabled via different provider/keywords/level. + // Ex 1. GCJoin_V2 is what we use to check whether the GC keyword is enabled in verbose level in the public provider + // Ex 2. SetGCHandle is what we use to check whether the GCHandle keyword is enabled in informational level in the public provider + // Refer to the comments in src/vm/gcenv.ee.h next to the EXTERN C definitions to see which events are enabled. + + // WARNING: To change an event's GC level, perfcollect script needs to be updated simultaneously to reflect it. + BOOL keyword_gc_verbose = EventXplatEnabledGCJoin_V2(); + BOOL keyword_gc_informational = EventXplatEnabledGCStart(); + + BOOL keyword_gc_heapsurvival_and_movement_informational = EventXplatEnabledGCGenerationRange(); + BOOL keyword_gchandle_informational = EventXplatEnabledSetGCHandle(); + BOOL keyword_gchandle_prv_informational = EventXplatEnabledPrvSetGCHandle(); + + BOOL prv_gcprv_informational = EventXplatEnabledBGCBegin(); + BOOL prv_gcprv_verbose = EventXplatEnabledPinPlugAtGCTime(); + + int publicProviderLevel = keyword_gc_verbose ? GCEventLevel_Verbose : (keyword_gc_informational ? GCEventLevel_Information : GCEventLevel_None); + int publicProviderKeywords = (keyword_gc_informational ? GCEventKeyword_GC : GCEventKeyword_None) | + (keyword_gchandle_informational ? GCEventKeyword_GCHandle : GCEventKeyword_None) | + (keyword_gc_heapsurvival_and_movement_informational ? GCEventKeyword_GCHeapSurvivalAndMovement : GCEventKeyword_None); + + int privateProviderLevel = prv_gcprv_verbose ? GCEventLevel_Verbose : (prv_gcprv_informational ? GCEventLevel_Information : GCEventLevel_None); + int privateProviderKeywords = (prv_gcprv_informational ? GCEventKeyword_GCPrivate : GCEventKeyword_None) | + (keyword_gchandle_prv_informational ? GCEventKeyword_GCHandlePrivate : GCEventKeyword_None); + + if (publicProviderLevel != currentPublicLevel || publicProviderKeywords != currentPublicKeywords) + { + GCEventLevel publicLevel = static_cast(publicProviderLevel); + GCEventKeyword publicKeywords = static_cast(publicProviderKeywords); + GCHeapUtilities::RecordEventStateChange(true, publicKeywords, publicLevel); + } + if (privateProviderLevel != currentPrivateLevel || privateProviderKeywords != currentPrivateKeywords) + { + GCEventLevel privateLevel = static_cast(privateProviderLevel); + GCEventKeyword privateKeywords = static_cast(privateProviderKeywords); + GCHeapUtilities::RecordEventStateChange(false, privateKeywords, privateLevel); + } +#endif // __linux__ +} diff --git a/src/coreclr/src/vm/gcenv.ee.h b/src/coreclr/src/vm/gcenv.ee.h index 08f9021..0b542ef 100644 --- a/src/coreclr/src/vm/gcenv.ee.h +++ b/src/coreclr/src/vm/gcenv.ee.h @@ -9,6 +9,19 @@ #ifdef FEATURE_STANDALONE_GC +#if defined(__linux__) +extern "C" BOOL EventXplatEnabledGCStart(); // GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC +extern "C" BOOL EventXPlatEnabledGCJoin_V2(); // GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC + +extern "C" BOOL EventXplatEnabledGCGenerationRange(); // GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHeapSurvivalAndMovement + +extern "C" BOOL EventXplatEnabledSetGCHandle(); // GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHandle +extern "C" BOOL EventXplatEnabledPrvSetGCHandle();; // GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCHandlePrivate + +extern "C" BOOL EventXplatEnabledBGCBegin(); // GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCPrivate +extern "C" BOOL EventXplatEnabledPinPlugAtGCTime(); // GCEventProvider_Private, GCEventLevel_Verbose, GCEventKeyword_GC +#endif // __linux__ + namespace standalone { @@ -74,6 +87,8 @@ public: void AnalyzeSurvivorsFinished(int condemnedGeneration); void VerifySyncTableEntry(); + + void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords); }; } // namespace standalone -- 2.7.4