diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 22d89cd1f80e1..d4248e71fe551 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_stackwalk_requested ( + uint8_t **buffer, + uint32_t *buffer_len, + bool *stackwalk_requested); + static bool eventpipe_collect_tracing_command_try_parse_config ( @@ -66,21 +73,21 @@ eventpipe_collect_tracing2_command_try_parse_payload ( uint16_t buffer_len); static -bool -eventpipe_protocol_helper_stop_tracing ( - DiagnosticsIpcMessage *message, - DiagnosticsIpcStream *stream); +uint8_t * +eventpipe_collect_tracing3_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len); static bool -eventpipe_protocol_helper_collect_tracing ( +eventpipe_protocol_helper_stop_tracing ( DiagnosticsIpcMessage *message, DiagnosticsIpcStream *stream); static bool -eventpipe_protocol_helper_collect_tracing_2 ( - DiagnosticsIpcMessage *message, +eventpipe_protocol_helper_collect_tracing ( + EventPipeCollectTracingCommandPayload *payload, DiagnosticsIpcStream *stream); static @@ -140,7 +147,22 @@ eventpipe_collect_tracing_command_try_parse_rundown_requested ( EP_ASSERT (buffer_len != NULL); EP_ASSERT (rundown_requested != NULL); - return ds_ipc_message_try_parse_value (buffer, buffer_len, (uint8_t *)rundown_requested, 1); + return ds_ipc_message_try_parse_bool (buffer, buffer_len, rundown_requested); +} + +static +inline +bool +eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( + uint8_t **buffer, + uint32_t *buffer_len, + bool *stackwalk_requested) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (stackwalk_requested != NULL); + + return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested); } static @@ -231,6 +253,30 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_exit_error_handler (); } +EventPipeCollectTracingCommandPayload * +ds_eventpipe_collect_tracing_command_payload_alloc (void) +{ + return ep_rt_object_alloc (EventPipeCollectTracingCommandPayload); +} + +void +ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload) +{ + ep_return_void_if_nok (payload != NULL); + ep_rt_byte_array_free (payload->incoming_buffer); + + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + } DN_VECTOR_FOREACH_END; + + ep_rt_object_free (payload); +} + +/* +* EventPipeCollectTracingCommandPayload +*/ + static uint8_t * eventpipe_collect_tracing_command_try_parse_payload ( @@ -251,6 +297,8 @@ eventpipe_collect_tracing_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) ep_raise_error (); + instance->rundown_requested = true; + instance->stackwalk_requested = true; ep_on_exit: return (uint8_t *)instance; @@ -261,30 +309,6 @@ eventpipe_collect_tracing_command_try_parse_payload ( ep_exit_error_handler (); } -EventPipeCollectTracingCommandPayload * -ds_eventpipe_collect_tracing_command_payload_alloc (void) -{ - return ep_rt_object_alloc (EventPipeCollectTracingCommandPayload); -} - -void -ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload) -{ - ep_return_void_if_nok (payload != NULL); - ep_rt_byte_array_free (payload->incoming_buffer); - - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - } DN_VECTOR_FOREACH_END; - - ep_rt_object_free (payload); -} - -/* -* EventPipeCollectTracing2CommandPayload -*/ - static uint8_t * eventpipe_collect_tracing2_command_try_parse_payload ( @@ -296,7 +320,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( uint8_t * buffer_cursor = buffer; uint32_t buffer_cursor_len = buffer_len; - EventPipeCollectTracing2CommandPayload *instance = ds_eventpipe_collect_tracing2_command_payload_alloc (); + EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); ep_raise_error_if_nok (instance != NULL); instance->incoming_buffer = buffer; @@ -306,34 +330,47 @@ 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->stackwalk_requested = true; ep_on_exit: return (uint8_t *)instance; ep_on_error: - ds_eventpipe_collect_tracing2_command_payload_free (instance); + ds_eventpipe_collect_tracing_command_payload_free (instance); instance = NULL; ep_exit_error_handler (); } -EventPipeCollectTracing2CommandPayload * -ds_eventpipe_collect_tracing2_command_payload_alloc (void) +static +uint8_t * +eventpipe_collect_tracing3_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len) { - return ep_rt_object_alloc (EventPipeCollectTracing2CommandPayload); -} + EP_ASSERT (buffer != NULL); -void -ds_eventpipe_collect_tracing2_command_payload_free (EventPipeCollectTracing2CommandPayload *payload) -{ - ep_return_void_if_nok (payload != NULL); - ep_rt_byte_array_free (payload->incoming_buffer); + uint8_t * buffer_cursor = buffer; + uint32_t buffer_cursor_len = buffer_len; - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - } DN_VECTOR_FOREACH_END; + EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); + ep_raise_error_if_nok (instance != NULL); - ep_rt_object_free (payload); + 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_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || + !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 (); + +ep_on_exit: + return (uint8_t *)instance; + +ep_on_error: + ds_eventpipe_collect_tracing_command_payload_free (instance); + instance = NULL; + ep_exit_error_handler (); } /* @@ -415,82 +452,34 @@ eventpipe_protocol_helper_stop_tracing ( static bool eventpipe_protocol_helper_collect_tracing ( - DiagnosticsIpcMessage *message, + EventPipeCollectTracingCommandPayload *payload, DiagnosticsIpcStream *stream) { - ep_return_false_if_nok (message != NULL && stream != NULL); - - bool result = false; - EventPipeCollectTracingCommandPayload *payload; - payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing_command_try_parse_payload); + ep_return_false_if_nok (stream != NULL); if (!payload) { ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); - ep_raise_error (); + return false; } - EventPipeSessionID session_id; - session_id = ep_enable ( + EventPipeSessionOptions options; + ep_session_options_init( + &options, NULL, payload->circular_buffer_size_in_mb, dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), dn_vector_size (payload->provider_configs), EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, - true, + payload->rundown_requested, + payload->stackwalk_requested, ds_ipc_stream_get_stream_ref (stream), NULL, NULL); - if (session_id == 0) { - ds_ipc_message_send_error (stream, DS_IPC_E_FAIL); - ep_raise_error (); - } else { - eventpipe_protocol_helper_send_start_tracing_success (stream, session_id); - ep_start_streaming (session_id); - } - - result = true; - -ep_on_exit: - ds_eventpipe_collect_tracing_command_payload_free (payload); - return result; - -ep_on_error: - EP_ASSERT (!result); - ds_ipc_stream_free (stream); - ep_exit_error_handler (); -} - -static -bool -eventpipe_protocol_helper_collect_tracing_2 ( - DiagnosticsIpcMessage *message, - DiagnosticsIpcStream *stream) -{ - ep_return_false_if_nok (message != NULL && stream != NULL); - + EventPipeSessionID session_id = 0; bool result = false; - EventPipeCollectTracing2CommandPayload *payload; - payload = (EventPipeCollectTracing2CommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing2_command_try_parse_payload); - - if (!payload) { - ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); - ep_raise_error (); - } - - EventPipeSessionID session_id; - session_id = ep_enable ( - NULL, - payload->circular_buffer_size_in_mb, - dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), - dn_vector_size (payload->provider_configs), - EP_SESSION_TYPE_IPCSTREAM, - payload->serialization_format, - payload->rundown_requested, - ds_ipc_stream_get_stream_ref (stream), - NULL, - NULL); + session_id = ep_enable_3(&options); if (session_id == 0) { ds_ipc_message_send_error (stream, DS_IPC_E_FAIL); @@ -503,7 +492,8 @@ eventpipe_protocol_helper_collect_tracing_2 ( result = true; ep_on_exit: - ds_eventpipe_collect_tracing2_command_payload_free (payload); + ep_session_options_fini(&options); + ds_eventpipe_collect_tracing_command_payload_free (payload); return result; ep_on_error: @@ -539,13 +529,20 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( ep_return_false_if_nok (message != NULL && stream != NULL); bool result = false; + EventPipeCollectTracingCommandPayload* payload = NULL; switch ((EventPipeCommandId)ds_ipc_header_get_commandid (ds_ipc_message_get_header_cref (message))) { case EP_COMMANDID_COLLECT_TRACING: - result = eventpipe_protocol_helper_collect_tracing (message, stream); + payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing_command_try_parse_payload); + result = eventpipe_protocol_helper_collect_tracing (payload, stream); break; case EP_COMMANDID_COLLECT_TRACING_2: - result = eventpipe_protocol_helper_collect_tracing_2 (message, stream); + payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing2_command_try_parse_payload); + result = eventpipe_protocol_helper_collect_tracing (payload, stream); + break; + case EP_COMMANDID_COLLECT_TRACING_3: + 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_STOP_TRACING: result = eventpipe_protocol_helper_stop_tracing (message, stream); diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index b8cbe9532fa8f..7a3c4ebd41ff3 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -18,6 +18,8 @@ */ // Command = 0x0202 +// Command = 0x0203 +// Command = 0x0204 #if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) struct _EventPipeCollectTracingCommandPayload { #else @@ -36,6 +38,8 @@ struct _EventPipeCollectTracingCommandPayload_Internal { dn_vector_t *provider_configs; uint32_t circular_buffer_size_in_mb; EventPipeSerializationFormat serialization_format; + bool rundown_requested; + bool stackwalk_requested; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) @@ -50,44 +54,6 @@ ds_eventpipe_collect_tracing_command_payload_alloc (void); void ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload); -/* -* EventPipeCollectTracing2CommandPayload -*/ - -// Command = 0x0202 -#if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) -struct _EventPipeCollectTracing2CommandPayload { -#else -struct _EventPipeCollectTracing2CommandPayload_Internal { -#endif - // The protocol buffer is defined as: - // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z - // message = uint circularBufferMB, uint format, array providers - // uint = 4 little endian bytes - // wchar = 2 little endian bytes, UTF16 encoding - // array = uint length, length # of Ts - // string = (array where the last char must = 0) or (length = 0) - // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data - - uint8_t *incoming_buffer; - dn_vector_t *provider_configs; - uint32_t circular_buffer_size_in_mb; - EventPipeSerializationFormat serialization_format; - bool rundown_requested; -}; - -#if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) -struct _EventPipeCollectTracing2CommandPayload { - uint8_t _internal [sizeof (struct _EventPipeCollectTracing2CommandPayload_Internal)]; -}; -#endif - -EventPipeCollectTracing2CommandPayload * -ds_eventpipe_collect_tracing2_command_payload_alloc (void); - -void -ds_eventpipe_collect_tracing2_command_payload_free (EventPipeCollectTracing2CommandPayload *payload); - /* * EventPipeStopTracingCommandPayload */ diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index 228a574068f54..8232d7d9b9db3 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -420,6 +420,23 @@ ds_ipc_message_try_parse_uint64_t ( return result; } +bool +ds_ipc_message_try_parse_bool ( + uint8_t **buffer, + uint32_t *buffer_len, + bool *value) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (value != NULL); + + uint8_t temp_value; + bool result = ds_ipc_message_try_parse_value (buffer, buffer_len, (uint8_t *)&temp_value, 1); + if (result) + *value = temp_value == 0 ? false : true; + return result; +} + bool ds_ipc_message_try_parse_uint32_t ( uint8_t **buffer, diff --git a/src/native/eventpipe/ds-protocol.h b/src/native/eventpipe/ds-protocol.h index df5b7aaa7d965..bb3a10120341d 100644 --- a/src/native/eventpipe/ds-protocol.h +++ b/src/native/eventpipe/ds-protocol.h @@ -111,6 +111,12 @@ ds_ipc_message_try_parse_value ( uint8_t *value, uint32_t value_len); +bool +ds_ipc_message_try_parse_bool ( + uint8_t **buffer, + uint32_t *buffer_len, + bool *value); + bool ds_ipc_message_try_parse_uint64_t ( uint8_t **buffer, diff --git a/src/native/eventpipe/ds-sources.c b/src/native/eventpipe/ds-sources.c index 66bc6a2b422a3..35e5568ca98b1 100644 --- a/src/native/eventpipe/ds-sources.c +++ b/src/native/eventpipe/ds-sources.c @@ -2,6 +2,8 @@ #ifdef ENABLE_PERFTRACING +#include "ds-types.h" + // Option to include all internal source files into ds-sources.c. #ifdef DS_INCLUDE_SOURCE_FILES #ifndef DS_FORCE_INCLUDE_SOURCE_FILES diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index fdbbf190a83cb..16d57f4cb7e89 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -35,7 +35,6 @@ typedef struct _DiagnosticsProcessInfoPayload DiagnosticsProcessInfoPayload; typedef struct _DiagnosticsProcessInfo2Payload DiagnosticsProcessInfo2Payload; typedef struct _DiagnosticsProcessInfo3Payload DiagnosticsProcessInfo3Payload; typedef struct _EventPipeCollectTracingCommandPayload EventPipeCollectTracingCommandPayload; -typedef struct _EventPipeCollectTracing2CommandPayload EventPipeCollectTracing2CommandPayload; typedef struct _EventPipeStopTracingCommandPayload EventPipeStopTracingCommandPayload; #include "ds-rt-types.h" @@ -104,6 +103,7 @@ typedef enum { EP_COMMANDID_STOP_TRACING = 0x01, EP_COMMANDID_COLLECT_TRACING = 0x02, EP_COMMANDID_COLLECT_TRACING_2 = 0x03, + EP_COMMANDID_COLLECT_TRACING_3 = 0x04, // future } EventPipeCommandId; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index ee134be65059d..a91dd108c2e99 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -134,6 +134,7 @@ ep_session_alloc ( EventPipeSessionType session_type, EventPipeSerializationFormat format, bool rundown_requested, + bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, uint32_t providers_len, @@ -208,7 +209,7 @@ ep_session_alloc ( instance->session_start_time = ep_system_timestamp_get (); instance->session_start_timestamp = ep_perf_timestamp_get (); instance->paused = false; - instance->enable_stackwalk = ep_rt_config_value_get_enable_stackwalk (); + instance->enable_stackwalk = ep_rt_config_value_get_enable_stackwalk () && stackwalk_requested; instance->started = 0; ep_on_exit: diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 6b26dc055e092..944b38c8e5d3d 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -59,7 +59,11 @@ struct _EventPipeSession_Internal { // we expect to remove it in the future once that limitation is resolved other scenarios are discouraged from using this given that // we plan to make it go away bool paused; - // Set via environment variable to enable or disable stack collection globally + // The callstacks are not always useful while the stackwalk can be very costly, especially with the frequent events + // Thus the stackwalk can be enabled or disabled per session + // By default the callstack collection is enabled + // The IPC option allows to disable the callstack collection for specific session + // The environment variable disables the callstack collection for all sessions (the IPC option will be ignored) bool enable_stackwalk; // Indicate that session is fully running (streaming thread started). volatile uint32_t started; @@ -89,6 +93,7 @@ ep_session_alloc ( EventPipeSessionType session_type, EventPipeSerializationFormat format, bool rundown_requested, + bool stackwalk_requested, uint32_t circular_buffer_size_in_mb, const EventPipeProviderConfiguration *providers, uint32_t providers_len, diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index d007702dde463..eeacb10e29c59 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -47,17 +47,8 @@ is_session_id_in_collection (EventPipeSessionID id); static EventPipeSessionID enable ( - const ep_char8_t *output_path, - uint32_t circular_buffer_size_in_mb, - const EventPipeProviderConfiguration *providers, - uint32_t providers_len, - EventPipeSessionType session_type, - EventPipeSerializationFormat format, - bool rundown_requested, - IpcStream *stream, - EventPipeProviderCallbackDataQueue *provider_callback_data_queue, - EventPipeSessionSynchronousCallback sync_callback, - void *callback_additional_data); + const EventPipeSessionOptions *options, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue); static void @@ -121,6 +112,10 @@ static bool ipc_stream_factory_any_suspended_ports (void); +static +bool +check_options_valid (const EventPipeSessionOptions *options); + /* * Global volatile variables, only to be accessed through inlined volatile access functions. */ @@ -455,27 +450,35 @@ is_session_id_in_collection (EventPipeSessionID session_id) return false; } +static bool check_options_valid (const EventPipeSessionOptions *options) +{ + if (options->format >= EP_SERIALIZATION_FORMAT_COUNT) + return false; + if (options->circular_buffer_size_in_mb <= 0 && options->session_type != EP_SESSION_TYPE_SYNCHRONOUS) + return false; + if (options->providers == NULL || options->providers_len <= 0) + return false; + if ((options->session_type == EP_SESSION_TYPE_FILE || options->session_type == EP_SESSION_TYPE_FILESTREAM) && options->output_path == NULL) + return false; + if (options->session_type == EP_SESSION_TYPE_IPCSTREAM && options->stream == NULL) + return false; + + return true; +} + static EventPipeSessionID enable ( - const ep_char8_t *output_path, - uint32_t circular_buffer_size_in_mb, - const EventPipeProviderConfiguration *providers, - uint32_t providers_len, - EventPipeSessionType session_type, - EventPipeSerializationFormat format, - bool rundown_requested, - IpcStream *stream, - EventPipeProviderCallbackDataQueue *provider_callback_data_queue, - EventPipeSessionSynchronousCallback sync_callback, - void *callback_additional_data) + const EventPipeSessionOptions *options, + EventPipeProviderCallbackDataQueue *provider_callback_data_queue) { - EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT); - EP_ASSERT (session_type == EP_SESSION_TYPE_SYNCHRONOUS || circular_buffer_size_in_mb > 0); - EP_ASSERT (providers_len > 0 && providers != NULL); - ep_requires_lock_held (); + EP_ASSERT (options != NULL); + EP_ASSERT (options->format < EP_SERIALIZATION_FORMAT_COUNT); + EP_ASSERT (options->session_type == EP_SESSION_TYPE_SYNCHRONOUS || options->circular_buffer_size_in_mb > 0); + EP_ASSERT (options->providers_len > 0 && options->providers != NULL); + EventPipeSession *session = NULL; EventPipeSessionID session_id = 0; uint32_t session_index = 0; @@ -487,16 +490,17 @@ enable ( session = ep_session_alloc ( session_index, - output_path, - stream, - session_type, - format, - rundown_requested, - circular_buffer_size_in_mb, - providers, - providers_len, - sync_callback, - callback_additional_data); + options->output_path, + options->stream, + options->session_type, + options->format, + options->rundown_requested, + options->stackwalk_requested, + options->circular_buffer_size_in_mb, + options->providers, + options->providers_len, + options->sync_callback, + options->callback_additional_data); ep_raise_error_if_nok (session != NULL && ep_session_is_valid (session)); @@ -960,52 +964,28 @@ ep_enable ( EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data) { - ep_return_zero_if_nok (format < EP_SERIALIZATION_FORMAT_COUNT); - ep_return_zero_if_nok (session_type == EP_SESSION_TYPE_SYNCHRONOUS || circular_buffer_size_in_mb > 0); - ep_return_zero_if_nok (providers_len > 0 && providers != NULL); - - ep_requires_lock_not_held (); + EventPipeSessionID sessionId = 0; - // If the state or arguments are invalid, bail here. - if ((session_type == EP_SESSION_TYPE_FILE || session_type == EP_SESSION_TYPE_FILESTREAM) && output_path == NULL) - return 0; - if (session_type == EP_SESSION_TYPE_IPCSTREAM && stream == NULL) - return 0; - - EventPipeSessionID session_id = 0; - EventPipeProviderCallbackDataQueue callback_data_queue; - EventPipeProviderCallbackData provider_callback_data; - EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); - - EP_LOCK_ENTER (section1) - session_id = enable ( - output_path, - circular_buffer_size_in_mb, - providers, - providers_len, - session_type, - format, - rundown_requested, - stream, - provider_callback_data_queue, - sync_callback, - callback_additional_data); - EP_LOCK_EXIT (section1) + EventPipeSessionOptions options; + ep_session_options_init( + &options, + output_path, + circular_buffer_size_in_mb, + providers, + providers_len, + session_type, + format, + rundown_requested, + true, // stackwalk_requested + stream, + sync_callback, + callback_additional_data); - while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { - ep_rt_prepare_provider_invoke_callback (&provider_callback_data); - provider_invoke_callback (&provider_callback_data); - ep_provider_callback_data_fini (&provider_callback_data); - } + sessionId = ep_enable_3(&options); -ep_on_exit: - ep_provider_callback_data_queue_fini (provider_callback_data_queue); - ep_requires_lock_not_held (); - return session_id; + ep_session_options_fini(&options); -ep_on_error: - session_id = 0; - ep_exit_error_handler (); + return sessionId; } EventPipeSessionID @@ -1116,6 +1096,72 @@ ep_enable_2 ( } +void +ep_session_options_init ( + EventPipeSessionOptions* options, + const ep_char8_t* output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration* providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + bool stackwalk_requested, + IpcStream* stream, + EventPipeSessionSynchronousCallback sync_callback, + void* callback_additional_data) +{ + EP_ASSERT (options != NULL); + + options->output_path = output_path; + options->circular_buffer_size_in_mb = circular_buffer_size_in_mb; + options->providers = providers; + options->providers_len = providers_len; + options->session_type = session_type; + options->format = format; + options->rundown_requested = rundown_requested; + options->stackwalk_requested = stackwalk_requested; + options->stream = stream; + options->sync_callback = sync_callback; + options->callback_additional_data = callback_additional_data; +} + +void +ep_session_options_fini (EventPipeSessionOptions* options) +{} + +EventPipeSessionID +ep_enable_3 (const EventPipeSessionOptions *options) +{ + ep_return_zero_if_nok (check_options_valid (options)); + + ep_requires_lock_not_held (); + + EventPipeSessionID session_id = 0; + EventPipeProviderCallbackDataQueue callback_data_queue; + EventPipeProviderCallbackData provider_callback_data; + EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); + + EP_LOCK_ENTER (section1) + session_id = enable (options, provider_callback_data_queue); + EP_LOCK_EXIT (section1) + + while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { + ep_rt_prepare_provider_invoke_callback (&provider_callback_data); + provider_invoke_callback (&provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); + } + +ep_on_exit: + ep_provider_callback_data_queue_fini (provider_callback_data_queue); + ep_requires_lock_not_held (); + return session_id; + +ep_on_error: + session_id = 0; + ep_exit_error_handler (); +} + void ep_disable (EventPipeSessionID id) { diff --git a/src/native/eventpipe/ep.h b/src/native/eventpipe/ep.h index 5073c52df8765..b7b31d04cdb03 100644 --- a/src/native/eventpipe/ep.h +++ b/src/native/eventpipe/ep.h @@ -105,6 +105,42 @@ ep_volatile_store_allow_write (uint64_t allow_write) ep_rt_volatile_store_uint64_t (&_ep_allow_write, allow_write); } +/* +* EventPipeSessionOptions. +*/ + +typedef struct EventPipeSessionOptions { + const EventPipeProviderConfiguration *providers; + IpcStream *stream; + const ep_char8_t *output_path; + void *callback_additional_data; + EventPipeSessionSynchronousCallback sync_callback; + uint32_t circular_buffer_size_in_mb; + uint32_t providers_len; + EventPipeSessionType session_type; + EventPipeSerializationFormat format; + bool rundown_requested; + bool stackwalk_requested; +} EventPipeSessionOptions; + +void +ep_session_options_init ( + EventPipeSessionOptions *options, + const ep_char8_t *output_path, + uint32_t circular_buffer_size_in_mb, + const EventPipeProviderConfiguration *providers, + uint32_t providers_len, + EventPipeSessionType session_type, + EventPipeSerializationFormat format, + bool rundown_requested, + bool stackwalk_requested, + IpcStream *stream, + EventPipeSessionSynchronousCallback sync_callback, + void *callback_additional_data); + +void +ep_session_options_fini (EventPipeSessionOptions* options); + /* * EventPipe. */ @@ -145,6 +181,11 @@ ep_enable_2 ( EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data); +EventPipeSessionID +ep_enable_3 ( + const EventPipeSessionOptions *options +); + void ep_disable (EventPipeSessionID id);