From 332a24d16177efc0f2afd134d6e04afd1030122b Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Fri, 19 Apr 2024 12:38:22 -0700 Subject: [PATCH] Allow user to specify a rundown keyword to override the default. (#101189) Co-authored-by: Noah Falk --- src/native/eventpipe/ds-eventpipe-protocol.c | 74 +++++++++++++++++++- src/native/eventpipe/ds-eventpipe-protocol.h | 2 + src/native/eventpipe/ds-types.h | 1 + src/native/eventpipe/ep-session.c | 16 +---- src/native/eventpipe/ep-session.h | 6 +- src/native/eventpipe/ep.c | 29 +++++--- src/native/eventpipe/ep.h | 14 ++-- 7 files changed, 112 insertions(+), 30 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index d4248e71fe551..b359102ee0d35 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -46,6 +46,13 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested ( uint32_t *buffer_len, bool *rundown_requested); +static +bool +eventpipe_collect_tracing_command_try_parse_rundown_keyword ( + uint8_t **buffer, + uint32_t *buffer_len, + uint64_t *rundown_keyword); + static bool eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( @@ -78,6 +85,12 @@ eventpipe_collect_tracing3_command_try_parse_payload ( uint8_t *buffer, uint16_t buffer_len); +static +uint8_t * +eventpipe_collect_tracing4_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len); + static bool eventpipe_protocol_helper_stop_tracing ( @@ -150,6 +163,21 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, rundown_requested); } +static +inline +bool +eventpipe_collect_tracing_command_try_parse_rundown_keyword ( + uint8_t **buffer, + uint32_t *buffer_len, + uint64_t *rundown_keyword) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (rundown_keyword != NULL); + + return ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, rundown_keyword); +} + static inline bool @@ -299,6 +327,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( ep_raise_error (); instance->rundown_requested = true; instance->stackwalk_requested = true; + instance->rundown_keyword = ep_default_rundown_keyword; ep_on_exit: return (uint8_t *)instance; @@ -330,6 +359,9 @@ eventpipe_collect_tracing2_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) ep_raise_error (); + + instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; + instance->stackwalk_requested = true; ep_on_exit: @@ -364,6 +396,42 @@ eventpipe_collect_tracing3_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) ep_raise_error (); + instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; + +ep_on_exit: + return (uint8_t *)instance; + +ep_on_error: + ds_eventpipe_collect_tracing_command_payload_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + +static +uint8_t * +eventpipe_collect_tracing4_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len) +{ + EP_ASSERT (buffer != NULL); + + uint8_t * buffer_cursor = buffer; + uint32_t buffer_cursor_len = buffer_len; + + EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); + ep_raise_error_if_nok (instance != NULL); + + instance->incoming_buffer = buffer; + + if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || + !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || + !eventpipe_collect_tracing_command_try_parse_rundown_keyword (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword) || + !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + ep_raise_error (); + + instance->rundown_requested = instance->rundown_keyword != 0; + ep_on_exit: return (uint8_t *)instance; @@ -471,7 +539,7 @@ eventpipe_protocol_helper_collect_tracing ( dn_vector_size (payload->provider_configs), EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, - payload->rundown_requested, + payload->rundown_keyword, payload->stackwalk_requested, ds_ipc_stream_get_stream_ref (stream), NULL, @@ -544,6 +612,10 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing3_command_try_parse_payload); result = eventpipe_protocol_helper_collect_tracing (payload, stream); break; + case EP_COMMANDID_COLLECT_TRACING_4: + payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing4_command_try_parse_payload); + result = eventpipe_protocol_helper_collect_tracing (payload, stream); + break; case EP_COMMANDID_STOP_TRACING: result = eventpipe_protocol_helper_stop_tracing (message, stream); break; diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 7a3c4ebd41ff3..14496068a109b 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -20,6 +20,7 @@ // Command = 0x0202 // Command = 0x0203 // Command = 0x0204 +// Command = 0x0205 #if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) struct _EventPipeCollectTracingCommandPayload { #else @@ -40,6 +41,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { EventPipeSerializationFormat serialization_format; bool rundown_requested; bool stackwalk_requested; + uint64_t rundown_keyword; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index 16d57f4cb7e89..a7596da6052a3 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -104,6 +104,7 @@ typedef enum { EP_COMMANDID_COLLECT_TRACING = 0x02, EP_COMMANDID_COLLECT_TRACING_2 = 0x03, EP_COMMANDID_COLLECT_TRACING_3 = 0x04, + EP_COMMANDID_COLLECT_TRACING_4 = 0x05, // future } EventPipeCommandId; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index a91dd108c2e99..c79d3972cd558 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -133,7 +133,7 @@ ep_session_alloc ( IpcStream *stream, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, @@ -164,7 +164,7 @@ ep_session_alloc ( instance->rundown_enabled = 0; instance->session_type = session_type; instance->format = format; - instance->rundown_requested = rundown_requested; + instance->rundown_keyword = rundown_keyword; instance->synchronous_callback = sync_callback; instance->callback_additional_data = callback_additional_data; @@ -317,17 +317,7 @@ ep_session_enable_rundown (EventPipeSession *session) ep_requires_lock_held (); bool result = false; - - //! This is CoreCLR specific keywords for native ETW events (ending up in event pipe). - //! The keywords below seems to correspond to: - //! GCKeyword (0x00000001) - //! LoaderKeyword (0x00000008) - //! JitKeyword (0x00000010) - //! NgenKeyword (0x00000020) - //! unused_keyword (0x00000100) - //! JittedMethodILToNativeMapKeyword (0x00020000) - //! ThreadTransferKeyword (0x80000000) - const uint64_t keywords = 0x80020139; + const uint64_t keywords = ep_session_get_rundown_keyword (session); const EventPipeEventLevel verbose_logging_level = EP_EVENT_LEVEL_VERBOSE; EventPipeProviderConfiguration rundown_provider; diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 944b38c8e5d3d..646c4ab566c08 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -53,7 +53,7 @@ struct _EventPipeSession_Internal { // irrelevant. EventPipeSerializationFormat format; // For determininig if a particular session needs rundown events. - bool rundown_requested; + uint64_t rundown_keyword; // Note - access to this field is NOT synchronized // This functionality is a workaround because we couldn't safely enable/disable the session where we wanted to due to lock-leveling. // we expect to remove it in the future once that limitation is resolved other scenarios are discouraged from using this given that @@ -79,7 +79,7 @@ EP_DEFINE_GETTER(EventPipeSession *, session, uint32_t, index) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeSessionProviderList *, providers) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeBufferManager *, buffer_manager) EP_DEFINE_GETTER_REF(EventPipeSession *, session, volatile uint32_t *, rundown_enabled) -EP_DEFINE_GETTER(EventPipeSession *, session, bool, rundown_requested) +EP_DEFINE_GETTER(EventPipeSession *, session, uint64_t, rundown_keyword) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_time) EP_DEFINE_GETTER(EventPipeSession *, session, ep_timestamp_t, session_start_timestamp) EP_DEFINE_GETTER(EventPipeSession *, session, EventPipeFile *, file) @@ -92,7 +92,7 @@ ep_session_alloc ( IpcStream *stream, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 7313fcb856dcd..b65326a16bcfa 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -15,6 +15,17 @@ #include "ep-session.h" #include "ep-sample-profiler.h" +//! This is CoreCLR specific keywords for native ETW events (ending up in event pipe). +//! The keywords below seems to correspond to: +//! GCKeyword (0x00000001) +//! LoaderKeyword (0x00000008) +//! JitKeyword (0x00000010) +//! NgenKeyword (0x00000020) +//! unused_keyword (0x00000100) +//! JittedMethodILToNativeMapKeyword (0x00020000) +//! ThreadTransferKeyword (0x80000000) +uint64_t ep_default_rundown_keyword = 0x80020139; + static bool _ep_can_start_threads = false; static dn_vector_t *_ep_deferred_enable_session_ids = NULL; @@ -494,7 +505,7 @@ enable ( options->stream, options->session_type, options->format, - options->rundown_requested, + options->rundown_keyword, options->stackwalk_requested, options->circular_buffer_size_in_mb, options->providers, @@ -589,7 +600,7 @@ disable_holding_lock ( ep_session_disable (session); // WriteAllBuffersToFile, and remove providers. // Do rundown before fully stopping the session unless rundown wasn't requested - if (ep_session_get_rundown_requested (session) && _ep_can_start_threads) { + if ((ep_session_get_rundown_keyword (session) != 0) && _ep_can_start_threads) { ep_session_enable_rundown (session); // Set Rundown provider. EventPipeThread *const thread = ep_thread_get_or_create (); if (thread != NULL) { @@ -908,7 +919,7 @@ enable_default_session_via_env_variables (void) ep_config, ep_rt_config_value_get_output_streaming () ? EP_SESSION_TYPE_FILESTREAM : EP_SESSION_TYPE_FILE, EP_SERIALIZATION_FORMAT_NETTRACE_V4, - true, + ep_default_rundown_keyword, NULL, NULL, NULL); @@ -959,7 +970,7 @@ ep_enable ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data) @@ -975,7 +986,7 @@ ep_enable ( providers_len, session_type, format, - rundown_requested, + rundown_keyword, true, // stackwalk_requested stream, sync_callback, @@ -995,7 +1006,7 @@ ep_enable_2 ( const ep_char8_t *providers_config, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data) @@ -1073,7 +1084,7 @@ ep_enable_2 ( providers_len, session_type, format, - rundown_requested, + rundown_keyword, stream, sync_callback, callback_additional_data); @@ -1105,7 +1116,7 @@ ep_session_options_init ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, IpcStream* stream, EventPipeSessionSynchronousCallback sync_callback, @@ -1119,7 +1130,7 @@ ep_session_options_init ( options->providers_len = providers_len; options->session_type = session_type; options->format = format; - options->rundown_requested = rundown_requested; + options->rundown_keyword = rundown_keyword; options->stackwalk_requested = stackwalk_requested; options->stream = stream; options->sync_callback = sync_callback; diff --git a/src/native/eventpipe/ep.h b/src/native/eventpipe/ep.h index b7b31d04cdb03..fd8c019121c1e 100644 --- a/src/native/eventpipe/ep.h +++ b/src/native/eventpipe/ep.h @@ -13,6 +13,12 @@ extern volatile EventPipeSession *_ep_sessions [EP_MAX_NUMBER_OF_SESSIONS]; extern volatile uint32_t _ep_number_of_sessions; extern volatile uint64_t _ep_allow_write; +/* + * Global constants + */ + +extern uint64_t ep_default_rundown_keyword; + /* * Globals and volatile access functions. */ @@ -119,7 +125,7 @@ typedef struct EventPipeSessionOptions { uint32_t providers_len; EventPipeSessionType session_type; EventPipeSerializationFormat format; - bool rundown_requested; + uint64_t rundown_keyword; bool stackwalk_requested; } EventPipeSessionOptions; @@ -132,7 +138,7 @@ ep_session_options_init ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, bool stackwalk_requested, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, @@ -164,7 +170,7 @@ ep_enable ( uint32_t providers_len, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data); @@ -176,7 +182,7 @@ ep_enable_2 ( const ep_char8_t *providers, EventPipeSessionType session_type, EventPipeSerializationFormat format, - bool rundown_requested, + uint64_t rundown_keyword, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data);