Fix how we check whether events are enabled via LTTng (dotnet/coreclr#22707)
authorSung Yoon Whang <suwhang@microsoft.com>
Fri, 8 Mar 2019 02:34:17 +0000 (18:34 -0800)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2019 02:34:17 +0000 (18:34 -0800)
* 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
src/coreclr/src/gc/gc.cpp
src/coreclr/src/gc/gcenv.ee.standalone.inl
src/coreclr/src/gc/gceventstatus.h
src/coreclr/src/gc/gcinterface.ee.h
src/coreclr/src/gc/gcinterface.h
src/coreclr/src/vm/gcenv.ee.cpp
src/coreclr/src/vm/gcenv.ee.h

index ec72517..c91eadb 100644 (file)
@@ -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__
index 95fe21c..a26ad8d 100644 (file)
@@ -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<int>(GCEventStatus::GetEnabledLevel(GCEventProvider_Default)),
+                                         static_cast<int>(GCEventStatus::GetEnabledKeywords(GCEventProvider_Default)),
+                                         static_cast<int>(GCEventStatus::GetEnabledLevel(GCEventProvider_Private)),
+                                         static_cast<int>(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<int>(GCEventStatus::GetEnabledLevel(GCEventProvider_Default)),
+                                         static_cast<int>(GCEventStatus::GetEnabledKeywords(GCEventProvider_Default)),
+                                         static_cast<int>(GCEventStatus::GetEnabledLevel(GCEventProvider_Private)),
+                                         static_cast<int>(GCEventStatus::GetEnabledKeywords(GCEventProvider_Private)));
+#endif // __linux__
 
     if (settings.concurrent)
     {
index b000dad..b5c2c76 100644 (file)
@@ -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__
index c49e767..1f31d42 100644 (file)
 // 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<size_t>(provider)].LoadWithoutBarrier();
+    }
+
+    /*
+     * Returns currently enabled keywords in GCPublic
+     */
+    static inline GCEventKeyword GetEnabledKeywords(GCEventProvider provider)
+    {
+        return enabledKeywords[static_cast<size_t>(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<typename... EventActualArgument>                       \
@@ -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
index 228bb37..4ce9203 100644 (file)
@@ -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_
index 249466a..9744eb0 100644 (file)
@@ -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
 {
index f27d3f3..7788022 100644 (file)
@@ -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<GCEventLevel>(publicProviderLevel);
+        GCEventKeyword publicKeywords = static_cast<GCEventKeyword>(publicProviderKeywords);
+        GCHeapUtilities::RecordEventStateChange(true, publicKeywords, publicLevel);
+    }
+    if (privateProviderLevel != currentPrivateLevel || privateProviderKeywords != currentPrivateKeywords)
+    {
+        GCEventLevel privateLevel = static_cast<GCEventLevel>(privateProviderLevel);
+        GCEventKeyword privateKeywords = static_cast<GCEventKeyword>(privateProviderKeywords);
+        GCHeapUtilities::RecordEventStateChange(false, privateKeywords, privateLevel);
+    }
+#endif // __linux__
+}
index 08f9021..0b542ef 100644 (file)
@@ -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