static void AnalyzeSurvivorsFinished(int condemnedGeneration);
static void VerifySyncTableEntry();
+ static void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords);
};
#endif // __GCENV_EE_H__
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;
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)
{
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__
// 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
#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)
* 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> \
#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
virtual
void VerifySyncTableEntry() = 0;
+
+ virtual
+ void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLEvel, int privateKeywords) = 0;
};
#endif // _GCINTERFACE_EE_H_
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
{
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__
+}
#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
{
void AnalyzeSurvivorsFinished(int condemnedGeneration);
void VerifySyncTableEntry();
+
+ void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords);
};
} // namespace standalone