diff --git a/src/coreclr/scripts/genEventPipe.py b/src/coreclr/scripts/genEventPipe.py
index 380710d4a009b2..1076b181e316d5 100644
--- a/src/coreclr/scripts/genEventPipe.py
+++ b/src/coreclr/scripts/genEventPipe.py
@@ -72,11 +72,19 @@ def generateMethodSignatureWrite(eventName, template, extern, runtimeFlavor):
sig_pieces.append(")")
return ''.join(sig_pieces)
+def includeProvider(providerName, runtimeFlavor):
+ if runtimeFlavor.coreclr and providerName == "Microsoft-DotNETRuntimeMonoProfiler":
+ return False
+ else:
+ return True
+
def includeEvent(inclusionList, providerName, eventName):
if len(inclusionList) == 0:
return True
if providerName in inclusionList and eventName in inclusionList[providerName]:
return True
+ elif providerName in inclusionList and "*" in inclusionList[providerName]:
+ return True
elif "*" in inclusionList and eventName in inclusionList["*"]:
return True
elif "*" in inclusionList and "*" in inclusionList["*"]:
@@ -340,6 +348,10 @@ def generateWriteEventBody(template, providerName, eventName, runtimeFlavor):
pack_list.append(
" success &= write_buffer_double_t(%s, &buffer, &offset, &size, &fixedBuffer);" %
(parameter.name,))
+ elif parameter.winType == "win:Pointer" and runtimeFlavor.mono:
+ pack_list.append(
+ " success &= write_buffer_uintptr_t((uintptr_t)%s, &buffer, &offset, &size, &fixedBuffer);" %
+ (parameter.name,))
elif runtimeFlavor.mono:
pack_list.append(
" success &= write_buffer((const uint8_t *)%s, sizeof(%s), &buffer, &offset, &size, &fixedBuffer);" %
@@ -669,16 +681,17 @@ def generateEventPipeHelperFile(etwmanifest, eventpipe_directory, target_cpp, ru
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
- providerPrettyName = providerName.replace("Windows-", '')
- providerPrettyName = providerPrettyName.replace("Microsoft-", '')
- providerPrettyName = providerPrettyName.replace('-', '_')
- if extern: helper.write(
- 'extern "C" '
- )
- helper.write(
- "void Init" +
- providerPrettyName +
- "(void);\n\n")
+ if includeProvider(providerName, runtimeFlavor):
+ providerPrettyName = providerName.replace("Windows-", '')
+ providerPrettyName = providerPrettyName.replace("Microsoft-", '')
+ providerPrettyName = providerPrettyName.replace('-', '_')
+ if extern: helper.write(
+ 'extern "C" '
+ )
+ helper.write(
+ "void Init" +
+ providerPrettyName +
+ "(void);\n\n")
if extern: helper.write(
'extern "C" '
@@ -687,10 +700,11 @@ def generateEventPipeHelperFile(etwmanifest, eventpipe_directory, target_cpp, ru
helper.write("void InitProvidersAndEvents(void)\n{\n")
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
- providerPrettyName = providerName.replace("Windows-", '')
- providerPrettyName = providerPrettyName.replace("Microsoft-", '')
- providerPrettyName = providerPrettyName.replace('-', '_')
- helper.write(" Init" + providerPrettyName + "();\n")
+ if includeProvider(providerName, runtimeFlavor):
+ providerPrettyName = providerName.replace("Windows-", '')
+ providerPrettyName = providerPrettyName.replace("Microsoft-", '')
+ providerPrettyName = providerPrettyName.replace('-', '_')
+ helper.write(" Init" + providerPrettyName + "();\n")
helper.write("}\n")
if runtimeFlavor.coreclr:
@@ -892,6 +906,19 @@ def getMonoEventPipeImplFilePrefix():
return write_buffer_int32_t (value, buffer, offset, size, fixed_buffer);
}
+static
+inline
+bool
+write_buffer_uintptr_t (
+ uintptr_t value,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer)
+{
+ return write_buffer ((const uint8_t *)&value, sizeof (uintptr_t), buffer, offset, size, fixed_buffer);
+}
+
static
inline
EventPipeEvent *
@@ -949,6 +976,8 @@ def generateEventPipeImplFiles(
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
+ if not includeProvider(providerName, runtimeFlavor):
+ continue
providerPrettyName = providerName.replace("Windows-", '')
providerPrettyName = providerPrettyName.replace("Microsoft-", '')
diff --git a/src/coreclr/vm/ClrEtwAll.man b/src/coreclr/vm/ClrEtwAll.man
index d8a275c6da6295..45895f16fce484 100644
--- a/src/coreclr/vm/ClrEtwAll.man
+++ b/src/coreclr/vm/ClrEtwAll.man
@@ -7052,6 +7052,930 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %3
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+ %5
+ %6
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+ %1
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+ %5
+ %6
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+ %1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+ %4
+ %5
+ %6
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+
+
+
+
+
+
+
+
+
+
+ %1
+ %2
+ %3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -8044,6 +8968,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/coreclr/vm/ClrEtwAllMeta.lst b/src/coreclr/vm/ClrEtwAllMeta.lst
index 285e9101c6321d..4ac4fe405d9da4 100644
--- a/src/coreclr/vm/ClrEtwAllMeta.lst
+++ b/src/coreclr/vm/ClrEtwAllMeta.lst
@@ -633,3 +633,33 @@ nomac:StressLogTask:::StressLogEvent_V1
# StackWalk events
##################
nomac:CLRStackStress:::CLRStackWalkStress
+
+#################################
+# Events from the Mono profiler provider
+#################################
+nostack::MonoProfiler::ExceptionClause
+nostack::MonoProfiler::MonoProfilerMethodEnter
+nostack::MonoProfiler::MonoProfilerMethodLeave
+nostack::MonoProfiler::MonoProfilerMethodTailCall
+nostack::MonoProfiler::MonoProfilerMethodExceptionLeave
+nostack::MonoProfiler::MonoProfilerMethodFree
+nostack::MonoProfiler::MonoProfilerMethodBeginInvoke
+nostack::MonoProfiler::MonoProfilerMethodEndInvoke
+nostack::MonoProfiler::MonoProfilerGCEvent
+nostack::MonoProfiler::MonoProfilerGCMoves
+nostack::MonoProfiler::MonoProfilerGCResize
+nostack::MonoProfiler::MonoProfilerGCFinalizing
+nostack::MonoProfiler::MonoProfilerGCFinalized
+nostack::MonoProfiler::MonoProfilerGCFinalizingObject
+nostack::MonoProfiler::MonoProfilerGCFinalizedObject
+nostack::MonoProfiler::MonoProfilerGCRootRegister
+nostack::MonoProfiler::MonoProfilerGCRootUnregister
+nostack::MonoProfiler::MonoProfilerGCRoots
+nostack::MonoProfiler::MonoProfilerGCHeapDumpStart
+nostack::MonoProfiler::MonoProfilerGCHeapDumpStop
+nostack::MonoProfiler::MonoProfilerGCHeapDumpObjectReference
+nostack::MonoProfiler::MonoProfilerThreadStarted
+nostack::MonoProfiler::MonoProfilerThreadStopping
+nostack::MonoProfiler::MonoProfilerThreadStopped
+nostack::MonoProfiler::MonoProfilerThreadExited
+nostack::MonoProfiler::MonoProfilerThreadName
\ No newline at end of file
diff --git a/src/mono/mono/component/event_pipe.c b/src/mono/mono/component/event_pipe.c
index 6ed6171875a03f..24aa0952ce7aa6 100644
--- a/src/mono/mono/component/event_pipe.c
+++ b/src/mono/mono/component/event_pipe.c
@@ -11,6 +11,8 @@
#include
#include
+static bool _event_pipe_component_inited = false;
+
struct _EventPipeProviderConfigurationNative {
gunichar2 *provider_name;
uint64_t keywords;
@@ -284,5 +286,11 @@ event_pipe_thread_ctrl_activity_id (
MonoComponentEventPipe *
mono_component_event_pipe_init (void)
{
+ if (!_event_pipe_component_inited) {
+ extern void ep_rt_mono_component_init (void);
+ ep_rt_mono_component_init ();
+ _event_pipe_component_inited = true;
+ }
+
return &fn_table;
}
diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c
index 9a83d80061bf55..683d94a61bb129 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono.c
+++ b/src/mono/mono/eventpipe/ep-rt-mono.c
@@ -16,11 +16,15 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
+#include
+#include "mono/utils/mono-logger-internals.h"
#include
#include
@@ -49,8 +53,11 @@ char *_ep_rt_mono_managed_cmd_line = NULL;
static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL;
static uint32_t _ep_rt_mono_max_sampled_thread_count = 32;
-// Mono profiler.
-static MonoProfilerHandle _ep_rt_mono_profiler = NULL;
+// Mono profilers.
+static MonoProfilerHandle _ep_rt_default_profiler = NULL;
+static MonoProfilerHandle _ep_rt_dotnet_runtime_profiler_provider = NULL;
+static MonoProfilerHandle _ep_rt_dotnet_mono_profiler_provider = NULL;
+static MonoCallSpec _ep_rt_dotnet_mono_profiler_provider_callspec = {0};
// Phantom JIT compile method.
MonoMethod *_ep_rt_mono_runtime_helper_compile_method = NULL;
@@ -196,6 +203,38 @@ typedef struct _AssemblyEventData AssemblyEventData;
#define EXCEPTION_THROWN_FLAGS_IS_CSE 0x8
#define EXCEPTION_THROWN_FLAGS_IS_CLS_COMPLIANT 0x10
+// Provider keyword flags.
+#define GC_KEYWORD 0x1
+#define GC_HANDLE_KEYWORD 0x2
+#define LOADER_KEYWORD 0x8
+#define JIT_KEYWORD 0x10
+#define APP_DOMAIN_RESOURCE_MANAGEMENT_KEYWORD 0x800
+#define CONTENTION_KEYWORD 0x4000
+#define EXCEPTION_KEYWORD 0x8000
+#define THREADING_KEYWORD 0x10000
+#define GC_ALLOCATION_KEYWORD 0x200000
+#define GC_MOVES_KEYWORD 0x400000
+#define GC_ROOT_KEYWORD 0x800000
+#define GC_FINALIZATION_KEYWORD 0x1000000
+#define GC_RESIZE_KEYWORD 0x2000000
+#define METHOD_TRACING_KEYWORD 0x20000000
+#define TYPE_DIAGNOSTIC_KEYWORD 0x8000000000
+#define TYPE_LOADING_KEYWORD 0x8000000000
+#define MONITOR_KEYWORD 0x10000000000
+#define METHOD_INSTRUMENTATION_KEYWORD 0x40000000000
+
+// GC provider types.
+
+typedef struct _GCObjectAddressData {
+ MonoObject *object;
+ void *address;
+} GCObjectAddressData;
+
+typedef struct _GCAddressObjectData {
+ void *address;
+ MonoObject *object;
+} GCAddressObjectData;
+
/*
* Forward declares of all static functions.
*/
@@ -303,6 +342,10 @@ profiler_eventpipe_thread_exited (
MonoProfiler *prof,
uintptr_t tid);
+static
+bool
+parse_mono_profiler_options (const ep_char8_t *option);
+
static
bool
get_module_event_data (
@@ -328,86 +371,86 @@ get_exception_ip_func (
static
void
-profiler_jit_begin (
+runtime_profiler_jit_begin (
MonoProfiler *prof,
MonoMethod *method);
static
void
-profiler_jit_failed (
+runtime_profiler_jit_failed (
MonoProfiler *prof,
MonoMethod *method);
static
void
-profiler_jit_done (
+runtime_profiler_jit_done (
MonoProfiler *prof,
MonoMethod *method,
MonoJitInfo *ji);
static
void
-profiler_image_loaded (
+runtime_profiler_image_loaded (
MonoProfiler *prof,
MonoImage *image);
static
void
-profiler_image_unloaded (
+runtime_profiler_image_unloaded (
MonoProfiler *prof,
MonoImage *image);
static
void
-profiler_assembly_loaded (
+runtime_profiler_assembly_loaded (
MonoProfiler *prof,
MonoAssembly *assembly);
static
void
-profiler_assembly_unloaded (
+runtime_profiler_assembly_unloaded (
MonoProfiler *prof,
MonoAssembly *assembly);
static
void
-profiler_thread_started (
+runtime_profiler_thread_started (
MonoProfiler *prof,
uintptr_t tid);
static
void
-profiler_thread_stopped (
+runtime_profiler_thread_stopped (
MonoProfiler *prof,
uintptr_t tid);
static
void
-profiler_class_loading (
+runtime_profiler_class_loading (
MonoProfiler *prof,
MonoClass *klass);
static
void
-profiler_class_failed (
+runtime_profiler_class_failed (
MonoProfiler *prof,
MonoClass *klass);
static
void
-profiler_class_loaded (
+runtime_profiler_class_loaded (
MonoProfiler *prof,
MonoClass *klass);
static
void
-profiler_exception_throw (
+runtime_profiler_exception_throw (
MonoProfiler *prof,
MonoObject *exception);
static
void
-profiler_exception_clause (
+runtime_profiler_exception_clause (
MonoProfiler *prof,
MonoMethod *method,
uint32_t clause_num,
@@ -416,2571 +459,4443 @@ profiler_exception_clause (
static
void
-profiler_monitor_contention (
+runtime_profiler_monitor_contention (
MonoProfiler *prof,
MonoObject *obj);
static
void
-profiler_monitor_acquired (
+runtime_profiler_monitor_acquired (
MonoProfiler *prof,
MonoObject *obj);
static
void
-profiler_monitor_failed (
+runtime_profiler_monitor_failed (
MonoProfiler *prof,
MonoObject *obj);
static
void
-profiler_jit_code_buffer (
+runtime_profiler_jit_code_buffer (
MonoProfiler *prof,
const mono_byte *buffer,
uint64_t size,
MonoProfilerCodeBufferType type,
const void *data);
-/*
- * Forward declares of all private functions (accessed using extern in ep-rt-mono.h).
- */
+static
+void
+mono_profiler_app_domain_loading (
+ MonoProfiler *prof,
+ MonoDomain *domain);
+static
void
-ep_rt_mono_init (void);
+mono_profiler_app_domain_loaded (
+ MonoProfiler *prof,
+ MonoDomain *domain);
+static
void
-ep_rt_mono_init_finish (void);
+mono_profiler_app_domain_unloading (
+ MonoProfiler *prof,
+ MonoDomain *domain);
+static
void
-ep_rt_mono_fini (void);
+mono_profiler_app_domain_unloaded (
+ MonoProfiler *prof,
+ MonoDomain *domain);
-bool
-ep_rt_mono_rand_try_get_bytes (
- uint8_t *buffer,
- size_t buffer_size);
+static
+void
+mono_profiler_app_domain_name (
+ MonoProfiler *prof,
+ MonoDomain *domain,
+ const char *name);
-EventPipeThread *
-ep_rt_mono_thread_get_or_create (void);
+static
+void
+mono_profiler_jit_begin (
+ MonoProfiler *prof,
+ MonoMethod *method);
-void *
-ep_rt_mono_thread_attach (bool background_thread);
+static
+void
+mono_profiler_jit_failed (
+ MonoProfiler *prof,
+ MonoMethod *method);
-void *
-ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type);
+static
+void
+mono_profiler_jit_done (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoJitInfo *ji);
+static
void
-ep_rt_mono_thread_detach (void);
+mono_profiler_jit_chunk_created (
+ MonoProfiler *prof,
+ const mono_byte *chunk,
+ uintptr_t size);
+static
void
-ep_rt_mono_thread_exited (void);
+mono_profiler_jit_chunk_destroyed (
+ MonoProfiler *prof,
+ const mono_byte *chunk);
-int64_t
-ep_rt_mono_perf_counter_query (void);
+static
+void
+mono_profiler_jit_code_buffer (
+ MonoProfiler *prof,
+ const mono_byte *buffer,
+ uint64_t size,
+ MonoProfilerCodeBufferType type,
+ const void *data);
-int64_t
-ep_rt_mono_perf_frequency_query (void);
+static
+void
+mono_profiler_class_loading (
+ MonoProfiler *prof,
+ MonoClass *klass);
+static
void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time);
+mono_profiler_class_failed (
+ MonoProfiler *prof,
+ MonoClass *klass);
-int64_t
-ep_rt_mono_system_timestamp_get (void);
+static
+void
+mono_profiler_class_loaded (
+ MonoProfiler *prof,
+ MonoClass *klass);
+static
void
-ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array);
+mono_profiler_vtable_loading (
+ MonoProfiler *prof,
+ MonoVTable *vtable);
+static
void
-ep_rt_mono_init_providers_and_events (void);
+mono_profiler_vtable_failed (
+ MonoProfiler *prof,
+ MonoVTable *vtable);
+static
void
-ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config);
+mono_profiler_vtable_loaded (
+ MonoProfiler *prof,
+ MonoVTable *vtable);
-bool
-ep_rt_mono_providers_validate_all_disabled (void);
+static
+void
+mono_profiler_module_loading (
+ MonoProfiler *prof,
+ MonoImage *image);
+static
void
-ep_rt_mono_fini_providers_and_events (void);
+mono_profiler_module_failed (
+ MonoProfiler *prof,
+ MonoImage *image);
-bool
-ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
- ep_rt_thread_handle_t sampling_thread,
- EventPipeEvent *sampling_event);
+static
+void
+mono_profiler_module_loaded (
+ MonoProfiler *prof,
+ MonoImage *image);
-bool
-ep_rt_mono_walk_managed_stack_for_thread (
- ep_rt_thread_handle_t thread,
- EventPipeStackContents *stack_contents);
+static
+void
+mono_profiler_module_unloading (
+ MonoProfiler *prof,
+ MonoImage *image);
-bool
-ep_rt_mono_method_get_simple_assembly_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len);
+static
+void
+mono_profiler_module_unloaded (
+ MonoProfiler *prof,
+ MonoImage *image);
-bool
-ep_rt_mono_method_get_full_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len);
+static
+void
+mono_profiler_assembly_loading (
+ MonoProfiler *prof,
+ MonoAssembly *assembly);
+static
void
-ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints);
+mono_profiler_assembly_loaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly);
static
-inline
-uint16_t
-clr_instance_get_id (void)
-{
- // Mono runtime id.
- return 9;
-}
+void
+mono_profiler_assembly_unloading (
+ MonoProfiler *prof,
+ MonoAssembly *assembly);
static
-bool
-fire_method_rundown_events_func (
- const uint64_t method_id,
- const uint64_t module_id,
- const uint64_t method_start_address,
- const uint32_t method_size,
- const uint32_t method_token,
- const uint32_t method_flags,
- const ep_char8_t *method_namespace,
- const ep_char8_t *method_name,
- const ep_char8_t *method_signature,
- const uint16_t count_of_map_entries,
- const uint32_t *il_offsets,
- const uint32_t *native_offsets,
- bool aot_method,
- bool verbose,
- void *user_data)
-{
- FireEtwMethodDCEndILToNativeMap (
- method_id,
- 0,
- 0,
- count_of_map_entries,
- il_offsets,
- native_offsets,
- clr_instance_get_id (),
- NULL,
- NULL);
+void
+mono_profiler_assembly_unloaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly);
- if (verbose) {
- FireEtwMethodDCEndVerbose_V1 (
- method_id,
- module_id,
- method_start_address,
- method_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_method_enter (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoProfilerCallContext *context);
- if (aot_method)
- FireEtwMethodDCEndVerbose_V1 (
- method_id,
- module_id,
- method_start_address,
- method_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id (),
- NULL,
- NULL);
- } else {
- FireEtwMethodDCEnd_V1 (
- method_id,
- module_id,
- method_start_address,
- method_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_method_leave (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoProfilerCallContext *context);
- if (aot_method)
- FireEtwMethodDCEnd_V1 (
- method_id,
- module_id,
- method_start_address,
- method_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
- clr_instance_get_id (),
- NULL,
- NULL);
- }
+static
+void
+mono_profiler_method_tail_call (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoMethod *target_method);
- return true;
-}
+static
+void
+mono_profiler_method_exception_leave (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoObject *exc);
static
-bool
-fire_assembly_rundown_events_func (
- const uint64_t domain_id,
- const uint64_t assembly_id,
- const uint32_t assembly_flags,
- const uint32_t binding_id,
- const ep_char8_t *assembly_name,
- const uint64_t module_id,
- const uint32_t module_flags,
- const uint32_t reserved_flags,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- void *user_data)
-{
- FireEtwModuleDCEnd_V2 (
- module_id,
- assembly_id,
- module_flags,
- reserved_flags,
- module_il_path,
- module_native_path,
- clr_instance_get_id (),
- managed_pdb_signature,
- managed_pdb_age,
- managed_pdb_build_path,
- native_pdb_signature,
- native_pdb_age,
- native_pdb_build_path,
- NULL,
- NULL);
+void
+mono_profiler_method_free (
+ MonoProfiler *prof,
+ MonoMethod *method);
- FireEtwDomainModuleDCEnd_V1 (
- module_id,
- assembly_id,
- domain_id,
- module_flags,
- reserved_flags,
- module_il_path,
- module_native_path,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_method_begin_invoke (
+ MonoProfiler *prof,
+ MonoMethod *method);
- FireEtwAssemblyDCEnd_V1 (
- assembly_id,
- domain_id,
- binding_id,
- assembly_flags,
- assembly_name,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_method_end_invoke (
+ MonoProfiler *prof,
+ MonoMethod *method);
- return true;
-}
+static
+MonoProfilerCallInstrumentationFlags
+mono_profiler_method_instrumentation (
+ MonoProfiler *prof,
+ MonoMethod *method);
static
-bool
-fire_domain_rundown_events_func (
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- void *user_data)
-{
- return FireEtwAppDomainDCEnd_V1 (
- domain_id,
- domain_flags,
- domain_name,
- domain_index,
- clr_instance_get_id (),
- NULL,
- NULL);
-}
+void
+mono_profiler_exception_throw (
+ MonoProfiler *prof,
+ MonoObject *exc);
static
void
-eventpipe_fire_method_events (
- MonoJitInfo *ji,
+mono_profiler_exception_clause (
+ MonoProfiler *prof,
MonoMethod *method,
- EventPipeFireMethodEventsData *events_data)
-{
- EP_ASSERT (ji != NULL);
- EP_ASSERT (events_data->domain != NULL);
- EP_ASSERT (events_data->method_events_func != NULL);
-
- uint64_t method_id = 0;
- uint64_t module_id = 0;
- uint64_t method_code_start = (uint64_t)ji->code_start;
- uint32_t method_code_size = (uint32_t)ji->code_size;
- uint32_t method_token = 0;
- uint32_t method_flags = 0;
- uint8_t kind = MONO_CLASS_DEF;
- char *method_namespace = NULL;
- const char *method_name = NULL;
- char *method_signature = NULL;
- bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE);
+ uint32_t clause_num,
+ MonoExceptionEnum clause_type,
+ MonoObject *exc);
- //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
+static
+void
+mono_profiler_gc_event (
+ MonoProfiler *prof,
+ MonoProfilerGCEvent gc_event,
+ uint32_t generation,
+ mono_bool serial);
- if (method) {
- method_id = (uint64_t)method;
- method_token = method->token;
+static
+void
+mono_profiler_gc_allocation (
+ MonoProfiler *prof,
+ MonoObject *object);
- if (mono_jit_info_get_generic_sharing_context (ji))
- method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
+static
+void
+mono_profiler_gc_moves (
+ MonoProfiler *prof,
+ MonoObject *const* objects,
+ uint64_t count);
- if (method->dynamic)
- method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
+static
+void
+mono_profiler_gc_resize (
+ MonoProfiler *prof,
+ uintptr_t size);
- if (!ji->from_aot && !ji->from_llvm) {
- method_flags |= METHOD_FLAGS_JITTED_METHOD;
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
- }
+static
+void
+mono_profiler_gc_handle_created (
+ MonoProfiler *prof,
+ uint32_t handle,
+ MonoGCHandleType type,
+ MonoObject * object);
- if (method->is_generic || method->is_inflated)
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+static
+void
+mono_profiler_gc_handle_deleted (
+ MonoProfiler *prof,
+ uint32_t handle,
+ MonoGCHandleType type);
- if (method->klass) {
- module_id = (uint64_t)m_class_get_image (method->klass);
- kind = m_class_get_class_kind (method->klass);
- if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
- }
+static
+void
+mono_profiler_gc_finalizing (MonoProfiler *prof);
- if (verbose) {
- method_name = method->name;
- method_signature = mono_signature_full_name (method->signature);
- if (method->klass)
- method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
- }
+static
+void
+mono_profiler_gc_finalized (MonoProfiler *prof);
- }
+static
+void
+mono_profiler_gc_root_register (
+ MonoProfiler *prof,
+ const mono_byte *start,
+ uintptr_t size,
+ MonoGCRootSource source,
+ const void * key,
+ const char * name);
- uint16_t offset_entries = 0;
- uint32_t *il_offsets = NULL;
- uint32_t *native_offsets = NULL;
+static
+void
+mono_profiler_gc_root_unregister (
+ MonoProfiler *prof,
+ const mono_byte *start);
- MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, events_data->domain) : NULL;
- if (debug_info) {
- offset_entries = debug_info->num_line_numbers;
- if (offset_entries != 0) {
- size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
- if (!events_data->buffer || needed_size > events_data->buffer_size) {
- g_free (events_data->buffer);
- events_data->buffer_size = (size_t)(needed_size * 1.5);
- events_data->buffer = g_new (uint8_t, events_data->buffer_size);
- }
+static
+void
+mono_profiler_gc_roots (
+ MonoProfiler *prof,
+ uint64_t count,
+ const mono_byte *const * addresses,
+ MonoObject *const * objects);
- if (events_data->buffer) {
- il_offsets = (uint32_t*)events_data->buffer;
- native_offsets = il_offsets + offset_entries;
+static
+void
+mono_profiler_monitor_contention (
+ MonoProfiler *prof,
+ MonoObject *object);
- for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
- il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
- native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
- }
- }
- }
+static
+void
+mono_profiler_monitor_failed (
+ MonoProfiler *prof,
+ MonoObject *object);
- mono_debug_free_method_jit_info (debug_info);
- }
+static
+void
+mono_profiler_monitor_acquired (
+ MonoProfiler *prof,
+ MonoObject *object);
- if (events_data->buffer && !il_offsets && !native_offsets) {
- // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
- EP_ASSERT (events_data->buffer_size >= sizeof (uint32_t) * 2);
- offset_entries = 1;
- il_offsets = (uint32_t*)events_data->buffer;
- native_offsets = il_offsets + offset_entries;
- il_offsets [0] = 0;
- native_offsets [0] = (uint32_t)ji->code_size;
- }
+static
+void
+mono_profiler_thread_started (
+ MonoProfiler *prof,
+ uintptr_t tid);
- events_data->method_events_func (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags,
- (ep_char8_t *)method_namespace,
- (ep_char8_t *)method_name,
- (ep_char8_t *)method_signature,
- offset_entries,
- il_offsets,
- native_offsets,
- (ji->from_aot || ji->from_llvm),
- verbose,
- NULL);
+static
+void
+mono_profiler_thread_stopping (
+ MonoProfiler *prof,
+ uintptr_t tid);
- g_free (method_namespace);
- g_free (method_signature);
-}
+static
+void
+mono_profiler_thread_stopped (
+ MonoProfiler *prof,
+ uintptr_t tid);
static
-inline
-bool
-include_method (MonoMethod *method)
-{
- if (!method) {
- return false;
- } else if (!m_method_is_wrapper (method)) {
- return true;
- } else {
- WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
- return (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) ? true : false;
- }
-}
+void
+mono_profiler_thread_exited (
+ MonoProfiler *prof,
+ uintptr_t tid);
static
void
-eventpipe_fire_method_events_func (
- MonoJitInfo *ji,
- void *user_data)
-{
- EventPipeFireMethodEventsData *events_data = (EventPipeFireMethodEventsData *)user_data;
- EP_ASSERT (events_data != NULL);
+mono_profiler_thread_name (
+ MonoProfiler *prof,
+ uintptr_t tid,
+ const char *name);
- if (ji && !ji->is_trampoline && !ji->async) {
- MonoMethod *method = jinfo_get_method (ji);
- if (include_method (method))
- eventpipe_fire_method_events (ji, method, events_data);
- }
-}
+/*
+ * Forward declares of all private functions (accessed using extern in ep-rt-mono.h).
+ */
-static
void
-eventpipe_fire_assembly_events (
- MonoDomain *domain,
- MonoAssembly *assembly,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func)
-{
- EP_ASSERT (domain != NULL);
- EP_ASSERT (assembly != NULL);
- EP_ASSERT (assembly_events_func != NULL);
-
- uint64_t domain_id = (uint64_t)domain;
- uint64_t module_id = (uint64_t)assembly->image;
- uint64_t assembly_id = (uint64_t)assembly;
-
- // TODO: Extract all module IL/Native paths and pdb metadata when available.
- const char *module_il_path = "";
- const char *module_il_pdb_path = "";
- const char *module_native_path = "";
- const char *module_native_pdb_path = "";
- uint8_t signature [EP_GUID_SIZE] = { 0 };
- uint32_t module_il_pdb_age = 0;
- uint32_t module_native_pdb_age = 0;
+ep_rt_mono_component_init (void);
- uint32_t reserved_flags = 0;
- uint64_t binding_id = 0;
+void
+ep_rt_mono_init (void);
- // Native methods are part of JIT table and already emitted.
- // TODO: FireEtwMethodDCEndVerbose_V1_or_V2 for all native methods in module as well?
+void
+ep_rt_mono_init_finish (void);
- // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
- uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE;
- if (assembly->image) {
- if (assembly->image->dynamic)
- module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
- if (assembly->image->aot_module)
- module_flags |= MODULE_FLAGS_NATIVE_MODULE;
+void
+ep_rt_mono_fini (void);
- module_il_path = assembly->image->filename ? assembly->image->filename : "";
- }
+bool
+ep_rt_mono_rand_try_get_bytes (
+ uint8_t *buffer,
+ size_t buffer_size);
- uint32_t assembly_flags = 0;
- if (assembly->dynamic)
- assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
+EventPipeThread *
+ep_rt_mono_thread_get_or_create (void);
- if (assembly->image && assembly->image->aot_module) {
- assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
- }
+void *
+ep_rt_mono_thread_attach (bool background_thread);
- char *assembly_name = mono_stringify_assembly_name (&assembly->aname);
+void *
+ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type);
- assembly_events_func (
- domain_id,
- assembly_id,
- assembly_flags,
- binding_id,
- (const ep_char8_t*)assembly_name,
- module_id,
- module_flags,
- reserved_flags,
- (const ep_char8_t *)module_il_path,
- (const ep_char8_t *)module_native_path,
- signature,
- module_il_pdb_age,
- (const ep_char8_t *)module_il_pdb_path,
- signature,
- module_native_pdb_age,
- (const ep_char8_t *)module_native_pdb_path,
- NULL);
+void
+ep_rt_mono_thread_detach (void);
- g_free (assembly_name);
-}
+void
+ep_rt_mono_thread_exited (void);
-static
-gboolean
-eventpipe_execute_rundown (
- ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
- ep_rt_mono_fire_method_rundown_events_func method_events_func)
-{
- EP_ASSERT (domain_events_func != NULL);
- EP_ASSERT (assembly_events_func != NULL);
- EP_ASSERT (method_events_func != NULL);
+int64_t
+ep_rt_mono_perf_counter_query (void);
- // Under netcore we only have root domain.
- MonoDomain *root_domain = mono_get_root_domain ();
- if (root_domain) {
- uint64_t domain_id = (uint64_t)root_domain;
+int64_t
+ep_rt_mono_perf_frequency_query (void);
- // Emit all functions in use (JIT, AOT and Interpreter).
- EventPipeFireMethodEventsData events_data;
- events_data.domain = root_domain;
- events_data.buffer_size = 1024 * sizeof(uint32_t);
- events_data.buffer = g_new (uint8_t, events_data.buffer_size);
- events_data.method_events_func = method_events_func;
+void
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time);
- // All called JIT/AOT methods should be included in jit info table.
- mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
+int64_t
+ep_rt_mono_system_timestamp_get (void);
- // All called interpreted methods should be included in interpreter jit info table.
- if (mono_get_runtime_callbacks ()->is_interpreter_enabled())
- mono_get_runtime_callbacks ()->interp_jit_info_foreach (eventpipe_fire_method_events_func, &events_data);
+void
+ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array);
- // Phantom methods injected in callstacks representing runtime functions.
- if (_ep_rt_mono_runtime_helper_compile_method_jitinfo && _ep_rt_mono_runtime_helper_compile_method)
- eventpipe_fire_method_events (_ep_rt_mono_runtime_helper_compile_method_jitinfo, _ep_rt_mono_runtime_helper_compile_method, &events_data);
- if (_ep_rt_mono_monitor_enter_method_jitinfo && _ep_rt_mono_monitor_enter_method)
- eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_method_jitinfo, _ep_rt_mono_monitor_enter_method, &events_data);
- if (_ep_rt_mono_monitor_enter_v4_method_jitinfo && _ep_rt_mono_monitor_enter_v4_method)
- eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_v4_method_jitinfo, _ep_rt_mono_monitor_enter_v4_method, &events_data);
+void
+ep_rt_mono_init_providers_and_events (void);
- g_free (events_data.buffer);
+void
+ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config);
- // Iterate all assemblies in domain.
- GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
- if (assemblies) {
- for (int i = 0; i < assemblies->len; ++i) {
- MonoAssembly *assembly = (MonoAssembly *)g_ptr_array_index (assemblies, i);
- if (assembly)
- eventpipe_fire_assembly_events (root_domain, assembly, assembly_events_func);
- }
- g_ptr_array_free (assemblies, TRUE);
- }
+bool
+ep_rt_mono_providers_validate_all_disabled (void);
- uint32_t domain_flags = DOMAIN_FLAGS_DEFAULT_DOMAIN | DOMAIN_FLAGS_EXECUTABLE_DOMAIN;
- const char *domain_name = root_domain->friendly_name ? root_domain->friendly_name : "";
- uint32_t domain_index = 1;
+void
+ep_rt_mono_fini_providers_and_events (void);
- domain_events_func (
- domain_id,
- domain_flags,
- (const ep_char8_t *)domain_name,
- domain_index,
- NULL);
- }
+bool
+ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
+ ep_rt_thread_handle_t sampling_thread,
+ EventPipeEvent *sampling_event);
- return TRUE;
-}
+bool
+ep_rt_mono_walk_managed_stack_for_thread (
+ ep_rt_thread_handle_t thread,
+ EventPipeStackContents *stack_contents);
-inline
-static
bool
-in_safe_point_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
-{
- EP_ASSERT (stack_content != NULL);
+ep_rt_mono_method_get_simple_assembly_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len);
- // If top of stack is a managed->native icall wrapper for one of the below subtypes, we are at a safe point frame.
- if (wrapper && ep_stack_contents_get_length (stack_content) == 0 && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
- (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_state_poll ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_safe_region_unbalanced ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_safe_region_unbalanced ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_unsafe_region_unbalanced ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_unsafe_region_unbalanced))
- return true;
+bool
+ep_rt_mono_method_get_full_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len);
- return false;
-}
+void
+ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints);
-inline
static
+inline
bool
-in_runtime_invoke_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
+profiler_callback_is_enabled (uint64_t enabled_keywords, uint64_t keyword)
{
- EP_ASSERT (stack_content != NULL);
-
- // If top of stack is a managed->native runtime invoke wrapper, we are at a managed frame.
- if (wrapper && ep_stack_contents_get_length (stack_content) == 0 &&
- (wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL ||
- wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT ||
- wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC ||
- wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL))
- return true;
-
- return false;
+ return (enabled_keywords & keyword) == keyword;
}
-inline
static
-bool
-in_monitor_enter_frame (WrapperInfo *wrapper)
+inline
+uint16_t
+clr_instance_get_id (void)
{
- if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
- (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_fast ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_internal))
- return true;
-
- return false;
+ // Mono runtime id.
+ return 9;
}
-inline
static
bool
-in_monitor_enter_v4_frame (WrapperInfo *wrapper)
+fire_method_rundown_events_func (
+ const uint64_t method_id,
+ const uint64_t module_id,
+ const uint64_t method_start_address,
+ const uint32_t method_size,
+ const uint32_t method_token,
+ const uint32_t method_flags,
+ const ep_char8_t *method_namespace,
+ const ep_char8_t *method_name,
+ const ep_char8_t *method_signature,
+ const uint16_t count_of_map_entries,
+ const uint32_t *il_offsets,
+ const uint32_t *native_offsets,
+ bool aot_method,
+ bool verbose,
+ void *user_data)
{
- if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
- (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_fast ||
- wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_internal))
- return true;
-
- return false;
-}
-
-static
+ FireEtwMethodDCEndILToNativeMap (
+ method_id,
+ 0,
+ 0,
+ count_of_map_entries,
+ il_offsets,
+ native_offsets,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ if (verbose) {
+ FireEtwMethodDCEndVerbose_V1 (
+ method_id,
+ module_id,
+ method_start_address,
+ method_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ if (aot_method)
+ FireEtwMethodDCEndVerbose_V1 (
+ method_id,
+ module_id,
+ method_start_address,
+ method_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+ } else {
+ FireEtwMethodDCEnd_V1 (
+ method_id,
+ module_id,
+ method_start_address,
+ method_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ if (aot_method)
+ FireEtwMethodDCEnd_V1 (
+ method_id,
+ module_id,
+ method_start_address,
+ method_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+ }
+
+ return true;
+}
+
+static
+bool
+fire_assembly_rundown_events_func (
+ const uint64_t domain_id,
+ const uint64_t assembly_id,
+ const uint32_t assembly_flags,
+ const uint32_t binding_id,
+ const ep_char8_t *assembly_name,
+ const uint64_t module_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_flags,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ void *user_data)
+{
+ FireEtwModuleDCEnd_V2 (
+ module_id,
+ assembly_id,
+ module_flags,
+ reserved_flags,
+ module_il_path,
+ module_native_path,
+ clr_instance_get_id (),
+ managed_pdb_signature,
+ managed_pdb_age,
+ managed_pdb_build_path,
+ native_pdb_signature,
+ native_pdb_age,
+ native_pdb_build_path,
+ NULL,
+ NULL);
+
+ FireEtwDomainModuleDCEnd_V1 (
+ module_id,
+ assembly_id,
+ domain_id,
+ module_flags,
+ reserved_flags,
+ module_il_path,
+ module_native_path,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ FireEtwAssemblyDCEnd_V1 (
+ assembly_id,
+ domain_id,
+ binding_id,
+ assembly_flags,
+ assembly_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ return true;
+}
+
+static
+bool
+fire_domain_rundown_events_func (
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
+ void *user_data)
+{
+ return FireEtwAppDomainDCEnd_V1 (
+ domain_id,
+ domain_flags,
+ domain_name,
+ domain_index,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+}
+
+static
+void
+eventpipe_fire_method_events (
+ MonoJitInfo *ji,
+ MonoMethod *method,
+ EventPipeFireMethodEventsData *events_data)
+{
+ EP_ASSERT (ji != NULL);
+ EP_ASSERT (events_data->domain != NULL);
+ EP_ASSERT (events_data->method_events_func != NULL);
+
+ uint64_t method_id = 0;
+ uint64_t module_id = 0;
+ uint64_t method_code_start = (uint64_t)ji->code_start;
+ uint32_t method_code_size = (uint32_t)ji->code_size;
+ uint32_t method_token = 0;
+ uint32_t method_flags = 0;
+ uint8_t kind = MONO_CLASS_DEF;
+ char *method_namespace = NULL;
+ const char *method_name = NULL;
+ char *method_signature = NULL;
+ bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE);
+
+ //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
+
+ if (method) {
+ method_id = (uint64_t)method;
+ method_token = method->token;
+
+ if (mono_jit_info_get_generic_sharing_context (ji))
+ method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
+
+ if (method->dynamic)
+ method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
+
+ if (!ji->from_aot && !ji->from_llvm) {
+ method_flags |= METHOD_FLAGS_JITTED_METHOD;
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
+ }
+
+ if (method->is_generic || method->is_inflated)
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+
+ if (method->klass) {
+ module_id = (uint64_t)m_class_get_image (method->klass);
+ kind = m_class_get_class_kind (method->klass);
+ if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+ }
+
+ if (verbose) {
+ method_name = method->name;
+ method_signature = mono_signature_full_name (method->signature);
+ if (method->klass)
+ method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+ }
+
+ }
+
+ uint16_t offset_entries = 0;
+ uint32_t *il_offsets = NULL;
+ uint32_t *native_offsets = NULL;
+
+ MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, events_data->domain) : NULL;
+ if (debug_info) {
+ offset_entries = debug_info->num_line_numbers;
+ if (offset_entries != 0) {
+ size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
+ if (!events_data->buffer || needed_size > events_data->buffer_size) {
+ g_free (events_data->buffer);
+ events_data->buffer_size = (size_t)(needed_size * 1.5);
+ events_data->buffer = g_new (uint8_t, events_data->buffer_size);
+ }
+
+ if (events_data->buffer) {
+ il_offsets = (uint32_t*)events_data->buffer;
+ native_offsets = il_offsets + offset_entries;
+
+ for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
+ il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
+ native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ }
+ }
+ }
+
+ mono_debug_free_method_jit_info (debug_info);
+ }
+
+ if (events_data->buffer && !il_offsets && !native_offsets) {
+ // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
+ EP_ASSERT (events_data->buffer_size >= sizeof (uint32_t) * 2);
+ offset_entries = 1;
+ il_offsets = (uint32_t*)events_data->buffer;
+ native_offsets = il_offsets + offset_entries;
+ il_offsets [0] = 0;
+ native_offsets [0] = (uint32_t)ji->code_size;
+ }
+
+ events_data->method_events_func (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags,
+ (ep_char8_t *)method_namespace,
+ (ep_char8_t *)method_name,
+ (ep_char8_t *)method_signature,
+ offset_entries,
+ il_offsets,
+ native_offsets,
+ (ji->from_aot || ji->from_llvm),
+ verbose,
+ NULL);
+
+ g_free (method_namespace);
+ g_free (method_signature);
+}
+
+static
+inline
+bool
+include_method (MonoMethod *method)
+{
+ if (!method) {
+ return false;
+ } else if (!m_method_is_wrapper (method)) {
+ return true;
+ } else {
+ WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
+ return (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) ? true : false;
+ }
+}
+
+static
+void
+eventpipe_fire_method_events_func (
+ MonoJitInfo *ji,
+ void *user_data)
+{
+ EventPipeFireMethodEventsData *events_data = (EventPipeFireMethodEventsData *)user_data;
+ EP_ASSERT (events_data != NULL);
+
+ if (ji && !ji->is_trampoline && !ji->async) {
+ MonoMethod *method = jinfo_get_method (ji);
+ if (include_method (method))
+ eventpipe_fire_method_events (ji, method, events_data);
+ }
+}
+
+static
+void
+eventpipe_fire_assembly_events (
+ MonoDomain *domain,
+ MonoAssembly *assembly,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func)
+{
+ EP_ASSERT (domain != NULL);
+ EP_ASSERT (assembly != NULL);
+ EP_ASSERT (assembly_events_func != NULL);
+
+ uint64_t domain_id = (uint64_t)domain;
+ uint64_t module_id = (uint64_t)assembly->image;
+ uint64_t assembly_id = (uint64_t)assembly;
+
+ // TODO: Extract all module IL/Native paths and pdb metadata when available.
+ const char *module_il_path = "";
+ const char *module_il_pdb_path = "";
+ const char *module_native_path = "";
+ const char *module_native_pdb_path = "";
+ uint8_t signature [EP_GUID_SIZE] = { 0 };
+ uint32_t module_il_pdb_age = 0;
+ uint32_t module_native_pdb_age = 0;
+
+ uint32_t reserved_flags = 0;
+ uint64_t binding_id = 0;
+
+ // Native methods are part of JIT table and already emitted.
+ // TODO: FireEtwMethodDCEndVerbose_V1_or_V2 for all native methods in module as well?
+
+ // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
+ uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE;
+ if (assembly->image) {
+ if (assembly->image->dynamic)
+ module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
+ if (assembly->image->aot_module)
+ module_flags |= MODULE_FLAGS_NATIVE_MODULE;
+
+ module_il_path = assembly->image->filename ? assembly->image->filename : "";
+ }
+
+ uint32_t assembly_flags = 0;
+ if (assembly->dynamic)
+ assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
+
+ if (assembly->image && assembly->image->aot_module) {
+ assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
+ }
+
+ char *assembly_name = mono_stringify_assembly_name (&assembly->aname);
+
+ assembly_events_func (
+ domain_id,
+ assembly_id,
+ assembly_flags,
+ binding_id,
+ (const ep_char8_t*)assembly_name,
+ module_id,
+ module_flags,
+ reserved_flags,
+ (const ep_char8_t *)module_il_path,
+ (const ep_char8_t *)module_native_path,
+ signature,
+ module_il_pdb_age,
+ (const ep_char8_t *)module_il_pdb_path,
+ signature,
+ module_native_pdb_age,
+ (const ep_char8_t *)module_native_pdb_path,
+ NULL);
+
+ g_free (assembly_name);
+}
+
+static
+gboolean
+eventpipe_execute_rundown (
+ ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
+ ep_rt_mono_fire_method_rundown_events_func method_events_func)
+{
+ EP_ASSERT (domain_events_func != NULL);
+ EP_ASSERT (assembly_events_func != NULL);
+ EP_ASSERT (method_events_func != NULL);
+
+ // Under netcore we only have root domain.
+ MonoDomain *root_domain = mono_get_root_domain ();
+ if (root_domain) {
+ uint64_t domain_id = (uint64_t)root_domain;
+
+ // Emit all functions in use (JIT, AOT and Interpreter).
+ EventPipeFireMethodEventsData events_data;
+ events_data.domain = root_domain;
+ events_data.buffer_size = 1024 * sizeof(uint32_t);
+ events_data.buffer = g_new (uint8_t, events_data.buffer_size);
+ events_data.method_events_func = method_events_func;
+
+ // All called JIT/AOT methods should be included in jit info table.
+ mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
+
+ // All called interpreted methods should be included in interpreter jit info table.
+ if (mono_get_runtime_callbacks ()->is_interpreter_enabled())
+ mono_get_runtime_callbacks ()->interp_jit_info_foreach (eventpipe_fire_method_events_func, &events_data);
+
+ // Phantom methods injected in callstacks representing runtime functions.
+ if (_ep_rt_mono_runtime_helper_compile_method_jitinfo && _ep_rt_mono_runtime_helper_compile_method)
+ eventpipe_fire_method_events (_ep_rt_mono_runtime_helper_compile_method_jitinfo, _ep_rt_mono_runtime_helper_compile_method, &events_data);
+ if (_ep_rt_mono_monitor_enter_method_jitinfo && _ep_rt_mono_monitor_enter_method)
+ eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_method_jitinfo, _ep_rt_mono_monitor_enter_method, &events_data);
+ if (_ep_rt_mono_monitor_enter_v4_method_jitinfo && _ep_rt_mono_monitor_enter_v4_method)
+ eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_v4_method_jitinfo, _ep_rt_mono_monitor_enter_v4_method, &events_data);
+
+ g_free (events_data.buffer);
+
+ // Iterate all assemblies in domain.
+ GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
+ if (assemblies) {
+ for (int i = 0; i < assemblies->len; ++i) {
+ MonoAssembly *assembly = (MonoAssembly *)g_ptr_array_index (assemblies, i);
+ if (assembly)
+ eventpipe_fire_assembly_events (root_domain, assembly, assembly_events_func);
+ }
+ g_ptr_array_free (assemblies, TRUE);
+ }
+
+ uint32_t domain_flags = DOMAIN_FLAGS_DEFAULT_DOMAIN | DOMAIN_FLAGS_EXECUTABLE_DOMAIN;
+ const char *domain_name = root_domain->friendly_name ? root_domain->friendly_name : "";
+ uint32_t domain_index = 1;
+
+ domain_events_func (
+ domain_id,
+ domain_flags,
+ (const ep_char8_t *)domain_name,
+ domain_index,
+ NULL);
+ }
+
+ return TRUE;
+}
+
+inline
+static
+bool
+in_safe_point_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
+{
+ EP_ASSERT (stack_content != NULL);
+
+ // If top of stack is a managed->native icall wrapper for one of the below subtypes, we are at a safe point frame.
+ if (wrapper && ep_stack_contents_get_length (stack_content) == 0 && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_state_poll ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_safe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_safe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_unsafe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_unsafe_region_unbalanced))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_runtime_invoke_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
+{
+ EP_ASSERT (stack_content != NULL);
+
+ // If top of stack is a managed->native runtime invoke wrapper, we are at a managed frame.
+ if (wrapper && ep_stack_contents_get_length (stack_content) == 0 &&
+ (wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_monitor_enter_frame (WrapperInfo *wrapper)
+{
+ if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_fast ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_internal))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_monitor_enter_v4_frame (WrapperInfo *wrapper)
+{
+ if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_fast ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_internal))
+ return true;
+
+ return false;
+}
+
+static
gboolean
eventpipe_walk_managed_stack_for_thread (
MonoStackFrameInfo *frame,
MonoContext *ctx,
EventPipeStackWalkData *stack_walk_data)
{
- EP_ASSERT (frame != NULL);
- EP_ASSERT (stack_walk_data != NULL);
+ EP_ASSERT (frame != NULL);
+ EP_ASSERT (stack_walk_data != NULL);
+
+ switch (frame->type) {
+ case FRAME_TYPE_DEBUGGER_INVOKE:
+ case FRAME_TYPE_MANAGED_TO_NATIVE:
+ case FRAME_TYPE_TRAMPOLINE:
+ case FRAME_TYPE_INTERP_TO_MANAGED:
+ case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
+ case FRAME_TYPE_INTERP_ENTRY:
+ stack_walk_data->top_frame = false;
+ return FALSE;
+ case FRAME_TYPE_JIT_ENTRY:
+ // Frame in JIT compiler at top of callstack, add phantom frame representing call into JIT compiler.
+ // Makes it possible to detect stacks waiting on JIT compiler.
+ if (_ep_rt_mono_runtime_helper_compile_method && stack_walk_data->top_frame)
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_runtime_helper_compile_method), _ep_rt_mono_runtime_helper_compile_method);
+ stack_walk_data->top_frame = false;
+ return FALSE;
+ case FRAME_TYPE_MANAGED:
+ case FRAME_TYPE_INTERP:
+ if (frame->ji) {
+ stack_walk_data->async_frame |= frame->ji->async;
+ MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
+ if (method && m_method_is_wrapper (method)) {
+ WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
+ if (in_safe_point_frame (stack_walk_data->stack_contents, wrapper)) {
+ stack_walk_data->safe_point_frame = true;
+ }else if (in_runtime_invoke_frame (stack_walk_data->stack_contents, wrapper)) {
+ stack_walk_data->runtime_invoke_frame = true;
+ } else if (_ep_rt_mono_monitor_enter_method && in_monitor_enter_frame (wrapper)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_method), _ep_rt_mono_monitor_enter_method);
+ } else if (_ep_rt_mono_monitor_enter_v4_method && in_monitor_enter_v4_frame (wrapper)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_v4_method), _ep_rt_mono_monitor_enter_v4_method);
+ } else if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
+ }
+ } else if (method && !m_method_is_wrapper (method)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
+ } else if (!method && frame->ji->async && !frame->ji->is_trampoline) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start), method);
+ }
+ }
+ stack_walk_data->top_frame = false;
+ return ep_stack_contents_get_length (stack_walk_data->stack_contents) >= EP_MAX_STACK_DEPTH;
+ default:
+ EP_UNREACHABLE ("eventpipe_walk_managed_stack_for_thread");
+ return FALSE;
+ }
+}
+
+static
+gboolean
+eventpipe_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data)
+{
+ return eventpipe_walk_managed_stack_for_thread (frame, ctx, (EventPipeStackWalkData *)data);
+}
+
+static
+gboolean
+eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data)
+{
+ EP_ASSERT (frame != NULL);
+ EP_ASSERT (data != NULL);
+
+ EventPipeSampleProfileStackWalkData *sample_data = (EventPipeSampleProfileStackWalkData *)data;
+
+ if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
+ switch (frame->type) {
+ case FRAME_TYPE_MANAGED:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ break;
+ case FRAME_TYPE_MANAGED_TO_NATIVE:
+ case FRAME_TYPE_TRAMPOLINE:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ break;
+ case FRAME_TYPE_JIT_ENTRY:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ break;
+ case FRAME_TYPE_INTERP:
+ sample_data->payload_data = frame->managed ? EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED : EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ break;
+ case FRAME_TYPE_INTERP_TO_MANAGED:
+ case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
+ break;
+ default:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ }
+ }
+
+ return eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_walk_data);
+}
+
+static
+void
+profiler_eventpipe_thread_exited (
+ MonoProfiler *prof,
+ uintptr_t tid)
+{
+ void ep_rt_mono_thread_exited (void);
+ ep_rt_mono_thread_exited ();
+}
+
+static bool
+parse_mono_profiler_options (const ep_char8_t *option)
+{
+ do {
+ if (!*option)
+ return false;
+
+ if (!strncmp (option, "alloc", 5)) {
+ mono_profiler_enable_allocations ();
+ option += 5;
+ } else if (!strncmp (option, "exception", 9)) {
+ mono_profiler_enable_clauses ();
+ option += 9;
+ /*} else if (!strncmp (option, "sample", 6)) {
+ mono_profiler_enable_sampling (_ep_rt_dotnet_mono_profiler_provider);
+ option += 6;*/
+ } else {
+ return false;
+ }
+
+ if (*option == ',')
+ option++;
+ } while (*option);
+
+ return true;
+}
+
+void
+ep_rt_mono_component_init (void)
+{
+ _ep_rt_default_profiler = mono_profiler_create (NULL);
+ _ep_rt_dotnet_runtime_profiler_provider = mono_profiler_create (NULL);
+ _ep_rt_dotnet_mono_profiler_provider = mono_profiler_create (NULL);
+
+ char *diag_env = g_getenv("MONO_DIAGNOSTICS");
+ if (diag_env) {
+ int diag_argc = 1;
+ char **diag_argv = g_new (char *, 1);
+ if (diag_argv) {
+ diag_argv [0] = NULL;
+ if (!mono_parse_options_from (diag_env, &diag_argc, &diag_argv)) {
+ for (int i = 0; i < diag_argc; ++i) {
+ if (diag_argv [i]) {
+ if (strncmp (diag_argv [i], "--diagnostic-mono-profiler=", 27) == 0) {
+ if (!parse_mono_profiler_options (diag_argv [i] + 27))
+ mono_trace (G_LOG_LEVEL_ERROR, MONO_TRACE_DIAGNOSTICS, "Failed parsing MONO_DIAGNOSTICS environment variable option: %s", diag_argv [i]);
+ } else if (strncmp (diag_argv [i], "--diagnostic-mono-profiler-callspec=", 36) == 0) {
+ char *errstr = NULL;
+ if (!mono_callspec_parse (diag_argv [i] + 36, &_ep_rt_dotnet_mono_profiler_provider_callspec, &errstr)) {
+ mono_trace (G_LOG_LEVEL_ERROR, MONO_TRACE_DIAGNOSTICS, "Failed parsing '%s': %s", diag_argv [i], errstr);
+ g_free (errstr);
+ mono_callspec_cleanup (&_ep_rt_dotnet_mono_profiler_provider_callspec);
+ } else {
+ mono_profiler_set_call_instrumentation_filter_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_instrumentation);
+ }
+ } else if (strncmp (diag_argv [i], "--diagnostic-ports=", 19) == 0) {
+ char *diag_ports_env = g_getenv("DOTNET_DiagnosticPorts");
+ if (diag_ports_env)
+ mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DIAGNOSTICS, "DOTNET_DiagnosticPorts environment variable already set, ignoring --diagnostic-ports used in MONO_DIAGNOSTICS environment variable");
+ else
+ g_setenv ("DOTNET_DiagnosticPorts", diag_argv [i] + 19, TRUE);
+ g_free (diag_ports_env);
+
+ } else {
+ mono_trace (G_LOG_LEVEL_ERROR, MONO_TRACE_DIAGNOSTICS, "Failed parsing MONO_DIAGNOSTICS environment variable, unknown option: %s", diag_argv [i]);
+ }
+
+ g_free (diag_argv [i]);
+ diag_argv [i] = NULL;
+ }
+ }
+
+ g_free (diag_argv);
+ } else {
+ mono_trace (G_LOG_LEVEL_ERROR, MONO_TRACE_DIAGNOSTICS, "Failed parsing MONO_DIAGNOSTICS environment variable");
+ }
+ }
+ }
+ g_free (diag_env);
+}
+
+void
+ep_rt_mono_init (void)
+{
+ mono_native_tls_alloc (&_ep_rt_mono_thread_holder_tls_id, NULL);
+
+ mono_100ns_ticks ();
+ mono_rand_open ();
+ _ep_rt_mono_rand_provider = mono_rand_init (NULL, 0);
+
+ _ep_rt_mono_initialized = TRUE;
+
+ EP_ASSERT (_ep_rt_default_profiler != NULL);
+ EP_ASSERT (_ep_rt_dotnet_runtime_profiler_provider != NULL);
+ EP_ASSERT (_ep_rt_dotnet_mono_profiler_provider != NULL);
+
+ mono_profiler_set_thread_stopped_callback (_ep_rt_default_profiler, profiler_eventpipe_thread_exited);
+
+ MonoMethodSignature *method_signature = mono_metadata_signature_alloc (mono_get_corlib (), 1);
+ if (method_signature) {
+ method_signature->params[0] = m_class_get_byval_arg (mono_get_object_class());
+ method_signature->ret = m_class_get_byval_arg (mono_get_void_class());
+
+ ERROR_DECL (error);
+ MonoClass *runtime_helpers = mono_class_from_name_checked (mono_get_corlib (), "System.Runtime.CompilerServices", "RuntimeHelpers", error);
+ if (is_ok (error) && runtime_helpers) {
+ MonoMethodBuilder *method_builder = mono_mb_new (runtime_helpers, "CompileMethod", MONO_WRAPPER_RUNTIME_INVOKE);
+ if (method_builder) {
+ _ep_rt_mono_runtime_helper_compile_method = mono_mb_create_method (method_builder, method_signature, 1);
+ mono_mb_free (method_builder);
+ }
+ }
+ mono_error_cleanup (error);
+ mono_metadata_free_method_signature (method_signature);
+
+ if (_ep_rt_mono_runtime_helper_compile_method) {
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_runtime_helper_compile_method) {
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_runtime_helper_compile_method);
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_size = 20;
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->d.method = _ep_rt_mono_runtime_helper_compile_method;
+ }
+ }
+ }
+
+ {
+ ERROR_DECL (error);
+ MonoMethodDesc *desc = NULL;
+ MonoClass *monitor = mono_class_from_name_checked (mono_get_corlib (), "System.Threading", "Monitor", error);
+ if (is_ok (error) && monitor) {
+ desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
+ if (desc) {
+ _ep_rt_mono_monitor_enter_v4_method = mono_method_desc_search_in_class (desc, monitor);
+ mono_method_desc_free (desc);
+
+ if (_ep_rt_mono_monitor_enter_v4_method) {
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_monitor_enter_v4_method_jitinfo) {
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_v4_method);
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_size = 20;
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_v4_method;
+ }
+ }
+ }
+
+ desc = mono_method_desc_new ("Monitor:Enter(object)", FALSE);
+ if (desc) {
+ _ep_rt_mono_monitor_enter_method = mono_method_desc_search_in_class (desc, monitor);
+ mono_method_desc_free (desc);
+
+ if (_ep_rt_mono_monitor_enter_method ) {
+ _ep_rt_mono_monitor_enter_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_monitor_enter_method_jitinfo) {
+ _ep_rt_mono_monitor_enter_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_method);
+ _ep_rt_mono_monitor_enter_method_jitinfo->code_size = 20;
+ _ep_rt_mono_monitor_enter_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_method;
+ }
+ }
+ }
+ }
+ mono_error_cleanup (error);
+ }
+}
+
+void
+ep_rt_mono_init_finish (void)
+{
+ if (mono_runtime_get_no_exec ())
+ return;
+
+ // Managed init of diagnostics classes, like registration of RuntimeEventSource (if available).
+ ERROR_DECL (error);
+
+ MonoClass *runtime_event_source = mono_class_from_name_checked (mono_get_corlib (), "System.Diagnostics.Tracing", "RuntimeEventSource", error);
+ if (is_ok (error) && runtime_event_source) {
+ MonoMethod *init = mono_class_get_method_from_name_checked (runtime_event_source, "Initialize", -1, 0, error);
+ if (is_ok (error) && init) {
+ mono_runtime_try_invoke_handle (init, NULL_HANDLE, NULL, error);
+ }
+ }
+
+ mono_error_cleanup (error);
+}
+
+void
+ep_rt_mono_fini (void)
+{
+ if (_ep_rt_mono_sampled_thread_callstacks)
+ g_array_free (_ep_rt_mono_sampled_thread_callstacks, TRUE);
+
+ if (_ep_rt_mono_initialized)
+ mono_rand_close (_ep_rt_mono_rand_provider);
+
+ g_free (_ep_rt_mono_runtime_helper_compile_method_jitinfo);
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo = NULL;
+
+ mono_free_method (_ep_rt_mono_runtime_helper_compile_method);
+ _ep_rt_mono_runtime_helper_compile_method = NULL;
+
+ g_free (_ep_rt_mono_monitor_enter_method_jitinfo);
+ _ep_rt_mono_monitor_enter_method_jitinfo = NULL;
+ _ep_rt_mono_monitor_enter_method = NULL;
+
+ g_free (_ep_rt_mono_monitor_enter_v4_method_jitinfo);
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo = NULL;
+ _ep_rt_mono_monitor_enter_v4_method = NULL;
+
+ if (_ep_rt_dotnet_mono_profiler_provider_callspec.enabled) {
+ mono_profiler_set_call_instrumentation_filter_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_callspec_cleanup (&_ep_rt_dotnet_mono_profiler_provider_callspec);
+ }
+
+ _ep_rt_mono_sampled_thread_callstacks = NULL;
+ _ep_rt_mono_rand_provider = NULL;
+ _ep_rt_mono_initialized = FALSE;
+}
+
+bool
+ep_rt_mono_rand_try_get_bytes (
+ uint8_t *buffer,
+ size_t buffer_size)
+{
+ EP_ASSERT (_ep_rt_mono_rand_provider != NULL);
+
+ ERROR_DECL (error);
+ return mono_rand_try_get_bytes (&_ep_rt_mono_rand_provider, (guchar *)buffer, (gssize)buffer_size, error);
+}
+
+EventPipeThread *
+ep_rt_mono_thread_get_or_create (void)
+{
+ EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
+ if (!thread_holder) {
+ thread_holder = thread_holder_alloc_func ();
+ mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, thread_holder);
+ }
+ return ep_thread_holder_get_thread (thread_holder);
+}
+
+void *
+ep_rt_mono_thread_attach (bool background_thread)
+{
+ MonoThread *thread = NULL;
+
+ // NOTE, under netcore, only root domain exists.
+ if (!mono_thread_current ()) {
+ thread = mono_thread_internal_attach (mono_get_root_domain ());
+ if (background_thread && thread) {
+ mono_thread_set_state (thread, ThreadState_Background);
+ mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
+ }
+ }
+
+ return thread;
+}
+
+void *
+ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type)
+{
+ void *result = ep_rt_mono_thread_attach (background_thread);
+ if (result && thread_type == EP_THREAD_TYPE_SAMPLING) {
+ // Increase sampling thread priority, accepting failures.
+#ifdef HOST_WIN32
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
+#elif _POSIX_PRIORITY_SCHEDULING
+ int policy;
+ int priority;
+ struct sched_param param;
+ int schedparam_result = pthread_getschedparam (pthread_self (), &policy, ¶m);
+ if (schedparam_result == 0) {
+ // Attempt to switch the thread to real time scheduling. This will not
+ // necessarily work on all OSs; for example, most Linux systems will give
+ // us EPERM here unless configured to allow this.
+ priority = param.sched_priority;
+ param.sched_priority = sched_get_priority_max (SCHED_RR);
+ if (param.sched_priority != -1) {
+ schedparam_result = pthread_setschedparam (pthread_self (), SCHED_RR, ¶m);
+ if (schedparam_result != 0) {
+ // Fallback, attempt to increase to max priority using current policy.
+ param.sched_priority = sched_get_priority_max (policy);
+ if (param.sched_priority != -1 && param.sched_priority != priority)
+ pthread_setschedparam (pthread_self (), policy, ¶m);
+ }
+ }
+ }
+#endif
+ }
+
+ return result;
+}
+
+void
+ep_rt_mono_thread_detach (void)
+{
+ MonoThread *current_thread = mono_thread_current ();
+ if (current_thread)
+ mono_thread_internal_detach (current_thread);
+}
+
+void
+ep_rt_mono_thread_exited (void)
+{
+ if (_ep_rt_mono_initialized) {
+ EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
+ if (thread_holder)
+ thread_holder_free_func (thread_holder);
+ mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, NULL);
+ }
+}
+
+#ifdef HOST_WIN32
+int64_t
+ep_rt_mono_perf_counter_query (void)
+{
+ LARGE_INTEGER value;
+ if (QueryPerformanceCounter (&value))
+ return (int64_t)value.QuadPart;
+ else
+ return 0;
+}
+
+int64_t
+ep_rt_mono_perf_frequency_query (void)
+{
+ LARGE_INTEGER value;
+ if (QueryPerformanceFrequency (&value))
+ return (int64_t)value.QuadPart;
+ else
+ return 0;
+}
+
+void
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
+{
+ SYSTEMTIME value;
+ GetSystemTime (&value);
+
+ EP_ASSERT (system_time != NULL);
+ ep_system_time_set (
+ system_time,
+ value.wYear,
+ value.wMonth,
+ value.wDayOfWeek,
+ value.wDay,
+ value.wHour,
+ value.wMinute,
+ value.wSecond,
+ value.wMilliseconds);
+}
+
+int64_t
+ep_rt_mono_system_timestamp_get (void)
+{
+ FILETIME value;
+ GetSystemTimeAsFileTime (&value);
+ return (int64_t)((((uint64_t)value.dwHighDateTime) << 32) | (uint64_t)value.dwLowDateTime);
+}
+#else
+#include
+#include
+#include
+#include
+
+#if HAVE_SYS_TIME_H
+#include
+#endif // HAVE_SYS_TIME_H
+
+#if HAVE_MACH_ABSOLUTE_TIME
+#include
+static mono_lazy_init_t _ep_rt_mono_time_base_info_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+static mach_timebase_info_data_t _ep_rt_mono_time_base_info = {0};
+#endif
+
+#ifdef HAVE_LOCALTIME_R
+#define HAVE_GMTIME_R 1
+#endif
+
+static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL;
+static const int64_t SECS_TO_100NS = 10000000;
+static const int64_t SECS_TO_NS = 1000000000;
+static const int64_t MSECS_TO_MIS = 1000;
+
+/* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */
+#if defined (HAVE_CLOCK_MONOTONIC) && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))
+#undef HAVE_CLOCK_MONOTONIC
+#endif
+
+#ifndef HAVE_CLOCK_MONOTONIC
+static const int64_t MISECS_TO_NS = 1000;
+#endif
+
+static
+void
+time_base_info_lazy_init (void);
+
+static
+int64_t
+system_time_to_int64 (
+ time_t sec,
+ long nsec);
+
+#if HAVE_MACH_ABSOLUTE_TIME
+static
+void
+time_base_info_lazy_init (void)
+{
+ kern_return_t result = mach_timebase_info (&_ep_rt_mono_time_base_info);
+ if (result != KERN_SUCCESS)
+ memset (&_ep_rt_mono_time_base_info, 0, sizeof (_ep_rt_mono_time_base_info));
+}
+#endif
+
+int64_t
+ep_rt_mono_perf_counter_query (void)
+{
+#if HAVE_MACH_ABSOLUTE_TIME
+ return (int64_t)mach_absolute_time ();
+#elif HAVE_CLOCK_MONOTONIC
+ struct timespec ts;
+ int result = clock_gettime (CLOCK_MONOTONIC, &ts);
+ if (result == 0)
+ return ((int64_t)(ts.tv_sec) * (int64_t)(SECS_TO_NS)) + (int64_t)(ts.tv_nsec);
+#else
+ #error "ep_rt_mono_perf_counter_get requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
+#endif
+ return 0;
+}
+
+int64_t
+ep_rt_mono_perf_frequency_query (void)
+{
+#if HAVE_MACH_ABSOLUTE_TIME
+ // (numer / denom) gives you the nanoseconds per tick, so the below code
+ // computes the number of ticks per second. We explicitly do the multiplication
+ // first in order to help minimize the error that is produced by integer division.
+ mono_lazy_initialize (&_ep_rt_mono_time_base_info_init, time_base_info_lazy_init);
+ if (_ep_rt_mono_time_base_info.denom == 0 || _ep_rt_mono_time_base_info.numer == 0)
+ return 0;
+ return ((int64_t)(SECS_TO_NS) * (int64_t)(_ep_rt_mono_time_base_info.denom)) / (int64_t)(_ep_rt_mono_time_base_info.numer);
+#elif HAVE_CLOCK_MONOTONIC
+ // clock_gettime () returns a result in terms of nanoseconds rather than a count. This
+ // means that we need to either always scale the result by the actual resolution (to
+ // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer
+ // the latter since it allows the highest throughput and should minimize error propagated
+ // to the user.
+ return (int64_t)(SECS_TO_NS);
+#else
+ #error "ep_rt_mono_perf_frequency_query requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
+#endif
+ return 0;
+}
+
+void
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
+{
+ time_t tt;
+#if HAVE_GMTIME_R
+ struct tm ut;
+#endif /* HAVE_GMTIME_R */
+ struct tm *ut_ptr;
+ struct timeval time_val;
+ int timeofday_retval;
+
+ EP_ASSERT (system_time != NULL);
+
+ tt = time (NULL);
+
+ /* We can't get millisecond resolution from time (), so we get it from gettimeofday () */
+ timeofday_retval = gettimeofday (&time_val, NULL);
+
+#if HAVE_GMTIME_R
+ ut_ptr = &ut;
+ if (gmtime_r (&tt, ut_ptr) == NULL)
+#else /* HAVE_GMTIME_R */
+ if ((ut_ptr = gmtime (&tt)) == NULL)
+#endif /* HAVE_GMTIME_R */
+ EP_UNREACHABLE ();
+
+ uint16_t milliseconds = 0;
+ if (timeofday_retval != -1) {
+ int old_seconds;
+ int new_seconds;
+
+ milliseconds = time_val.tv_usec / MSECS_TO_MIS;
+
+ old_seconds = ut_ptr->tm_sec;
+ new_seconds = time_val.tv_sec % 60;
+
+ /* just in case we reached the next second in the interval between time () and gettimeofday () */
+ if (old_seconds != new_seconds)
+ milliseconds = 999;
+ }
+
+ ep_system_time_set (
+ system_time,
+ 1900 + ut_ptr->tm_year,
+ ut_ptr->tm_mon + 1,
+ ut_ptr->tm_wday,
+ ut_ptr->tm_mday,
+ ut_ptr->tm_hour,
+ ut_ptr->tm_min,
+ ut_ptr->tm_sec,
+ milliseconds);
+}
+
+static
+inline
+int64_t
+system_time_to_int64 (
+ time_t sec,
+ long nsec)
+{
+ return ((int64_t)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + (nsec / 100);
+}
+
+int64_t
+ep_rt_mono_system_timestamp_get (void)
+{
+#if HAVE_CLOCK_MONOTONIC
+ struct timespec time;
+ if (clock_gettime (CLOCK_REALTIME, &time) == 0)
+ return system_time_to_int64 (time.tv_sec, time.tv_nsec);
+#else
+ struct timeval time;
+ if (gettimeofday (&time, NULL) == 0)
+ return system_time_to_int64 (time.tv_sec, time.tv_usec * MISECS_TO_NS);
+#endif
+ else
+ return system_time_to_int64 (0, 0);
+}
+#endif
+
+#ifndef HOST_WIN32
+#if defined(__APPLE__)
+#if defined (TARGET_OSX)
+G_BEGIN_DECLS
+gchar ***_NSGetEnviron(void);
+G_END_DECLS
+#define environ (*_NSGetEnviron())
+#else
+static char *_ep_rt_mono_environ[1] = { NULL };
+#define environ _ep_rt_mono_environ
+#endif /* defined (TARGET_OSX) */
+#else
+G_BEGIN_DECLS
+extern char **environ;
+G_END_DECLS
+#endif /* defined (__APPLE__) */
+#endif /* !defined (HOST_WIN32) */
+
+void
+ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
+{
+ EP_ASSERT (env_array != NULL);
+#ifdef HOST_WIN32
+ LPWSTR envs = GetEnvironmentStringsW ();
+ if (envs) {
+ LPWSTR next = envs;
+ while (*next) {
+ ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (next));
+ next += ep_rt_utf16_string_len (next) + 1;
+ }
+ FreeEnvironmentStringsW (envs);
+ }
+#else
+ gchar **next = NULL;
+ for (next = environ; *next != NULL; ++next)
+ ep_rt_env_array_utf16_append (env_array, ep_rt_utf8_to_utf16_string (*next, -1));
+#endif
+}
+
+void
+ep_rt_mono_init_providers_and_events (void)
+{
+ extern void InitProvidersAndEvents (void);
+ InitProvidersAndEvents ();
+}
+
+void
+ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config)
+{
+ if (!ep_rt_utf8_string_compare (ep_config_get_rundown_provider_name_utf8 (), ep_provider_config_get_provider_name (provider_config))) {
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = ep_provider_config_get_logging_level (provider_config);
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = ep_provider_config_get_keywords (provider_config);
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = true;
+ }
+}
+
+bool
+ep_rt_mono_providers_validate_all_disabled (void)
+{
+ return (!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled &&
+ !MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled &&
+ !MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled &&
+ !MICROSOFT_DOTNETRUNTIME_MONO_PROFILER_PROVIDER_EVENTPIPE_Context.IsEnabled);
+}
+
+void
+ep_rt_mono_fini_providers_and_events (void)
+{
+ // dotnet/runtime: issue 12775: EventPipe shutdown race conditions
+ // Deallocating providers/events here might cause AV if a WriteEvent
+ // was to occur. Thus, we are not doing this cleanup.
+}
+
+bool
+ep_rt_mono_walk_managed_stack_for_thread (
+ ep_rt_thread_handle_t thread,
+ EventPipeStackContents *stack_contents)
+{
+ EP_ASSERT (thread != NULL && stack_contents != NULL);
+
+ EventPipeStackWalkData stack_walk_data;
+ stack_walk_data.stack_contents = stack_contents;
+ stack_walk_data.top_frame = true;
+ stack_walk_data.async_frame = false;
+ stack_walk_data.safe_point_frame = false;
+ stack_walk_data.runtime_invoke_frame = false;
+
+ if (thread == ep_rt_thread_get_handle () && mono_get_eh_callbacks ()->mono_walk_stack_with_ctx)
+ mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
+ else if (mono_get_eh_callbacks ()->mono_walk_stack_with_state)
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
+
+ return true;
+}
+
+bool
+ep_rt_mono_method_get_simple_assembly_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len)
+{
+ EP_ASSERT (method != NULL);
+ EP_ASSERT (name != NULL);
+
+ MonoClass *method_class = mono_method_get_class (method);
+ MonoImage *method_image = method_class ? mono_class_get_image (method_class) : NULL;
+ const ep_char8_t *assembly_name = method_image ? mono_image_get_name (method_image) : NULL;
+
+ if (!assembly_name)
+ return false;
+
+ g_strlcpy (name, assembly_name, name_len);
+ return true;
+}
+
+bool
+ep_rt_mono_method_get_full_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len)
+{
+ EP_ASSERT (method != NULL);
+ EP_ASSERT (name != NULL);
+
+ char *full_method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
+ if (!full_method_name)
+ return false;
+
+ g_strlcpy (name, full_method_name, name_len);
+
+ g_free (full_method_name);
+ return true;
+}
+
+bool
+ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
+ ep_rt_thread_handle_t sampling_thread,
+ EventPipeEvent *sampling_event)
+{
+ // Follows CoreClr implementation of sample profiler. Generic invasive/expensive way to do CPU sample profiling relying on STW and stackwalks.
+ // TODO: Investigate alternatives on platforms supporting Signals/SuspendThread (see Mono profiler) or CPU PMU's (see ETW/perf_event_open).
+
+ // Sample profiler only runs on one thread, no need to synchorinize.
+ if (!_ep_rt_mono_sampled_thread_callstacks)
+ _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileStackWalkData), _ep_rt_mono_max_sampled_thread_count);
+
+ // Make sure there is room based on previous max number of sampled threads.
+ // NOTE, there is a chance there are more threads than max, if that's the case we will
+ // miss those threads in this sample, but will be included in next when max has been adjusted.
+ g_array_set_size (_ep_rt_mono_sampled_thread_callstacks, _ep_rt_mono_max_sampled_thread_count);
+
+ uint32_t filtered_thread_count = 0;
+ uint32_t sampled_thread_count = 0;
+
+ mono_stop_world (MONO_THREAD_INFO_FLAGS_NO_GC);
+
+ gboolean async_context = mono_thread_info_is_async_context ();
+ mono_thread_info_set_is_async_context (TRUE);
+
+ // Record all info needed in sample events while runtime is suspended, must be async safe.
+ FOREACH_THREAD_SAFE_EXCLUDE (thread_info, MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
+ if (!mono_thread_info_is_running (thread_info)) {
+ MonoThreadUnwindState *thread_state = mono_thread_info_get_suspend_state (thread_info);
+ if (thread_state->valid) {
+ if (sampled_thread_count < _ep_rt_mono_max_sampled_thread_count) {
+ EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, sampled_thread_count);
+ data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
+ data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
+ data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
+ data->stack_walk_data.stack_contents = &data->stack_contents;
+ data->stack_walk_data.top_frame = true;
+ data->stack_walk_data.async_frame = false;
+ data->stack_walk_data.safe_point_frame = false;
+ data->stack_walk_data.runtime_invoke_frame = false;
+ ep_stack_contents_reset (&data->stack_contents);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
+ if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && (data->stack_walk_data.safe_point_frame || data->stack_walk_data.runtime_invoke_frame)) {
+ // If classified as external code (managed->native frame on top of stack), but have a safe point or runtime invoke frame
+ // as second, re-classify current callstack to be executing managed code.
+ data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ }
+
+ sampled_thread_count++;
+ }
+ }
+ }
+ filtered_thread_count++;
+ } FOREACH_THREAD_SAFE_END
+
+ mono_thread_info_set_is_async_context (async_context);
+ mono_restart_world (MONO_THREAD_INFO_FLAGS_NO_GC);
+
+ // Fire sample event for threads. Must be done after runtime is resumed since it's not async safe.
+ // Since we can't keep thread info around after runtime as been suspended, use an empty
+ // adapter instance and only set recorded tid as parameter inside adapter.
+ THREAD_INFO_TYPE adapter = { { 0 } };
+ for (uint32_t i = 0; i < sampled_thread_count; ++i) {
+ EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, i);
+ if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) {
+ // Check if we have an async frame, if so we will need to make sure all frames are registered in regular jit info table.
+ // TODO: An async frame can contain wrapper methods (no way to check during stackwalk), we could skip writing profile event
+ // for this specific stackwalk or we could cleanup stack_frames before writing profile event.
+ if (data->stack_walk_data.async_frame) {
+ for (int i = 0; i < data->stack_contents.next_available_frame; ++i)
+ mono_jit_info_table_find_internal ((gpointer)data->stack_contents.stack_frames [i], TRUE, FALSE);
+ }
+ mono_thread_info_set_tid (&adapter, ep_rt_uint64_t_to_thread_id_t (data->thread_id));
+ ep_write_sample_profile_event (sampling_thread, sampling_event, &adapter, &data->stack_contents, (uint8_t *)&data->payload_data, sizeof (data->payload_data));
+ }
+ }
+
+ // Current thread count will be our next maximum sampled threads.
+ _ep_rt_mono_max_sampled_thread_count = filtered_thread_count;
+
+ return true;
+}
+
+void
+ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints)
+{
+ ep_char8_t runtime_module_path [256];
+ const uint8_t object_guid [EP_GUID_SIZE] = { 0 };
+ const uint16_t runtime_product_qfe_version = 0;
+ const uint32_t startup_flags = 0;
+ const uint8_t startup_mode = 0;
+ const ep_char8_t *command_line = "";
+
+ if (!g_module_address ((void *)mono_init, runtime_module_path, sizeof (runtime_module_path), NULL, NULL, 0, NULL))
+ runtime_module_path [0] = '\0';
+
+ FireEtwRuntimeInformationDCStart (
+ clr_instance_get_id (),
+ RUNTIME_SKU_CORECLR,
+ RuntimeProductMajorVersion,
+ RuntimeProductMinorVersion,
+ RuntimeProductPatchVersion,
+ runtime_product_qfe_version,
+ RuntimeFileMajorVersion,
+ RuntimeFileMajorVersion,
+ RuntimeFileBuildVersion,
+ RuntimeFileRevisionVersion,
+ startup_mode,
+ startup_flags,
+ command_line,
+ object_guid,
+ runtime_module_path,
+ NULL,
+ NULL);
+
+ if (execution_checkpoints) {
+ ep_rt_execution_checkpoint_array_iterator_t execution_checkpoints_iterator = ep_rt_execution_checkpoint_array_iterator_begin (execution_checkpoints);
+ while (!ep_rt_execution_checkpoint_array_iterator_end (execution_checkpoints, &execution_checkpoints_iterator)) {
+ EventPipeExecutionCheckpoint *checkpoint = ep_rt_execution_checkpoint_array_iterator_value (&execution_checkpoints_iterator);
+ FireEtwExecutionCheckpointDCEnd (
+ clr_instance_get_id (),
+ checkpoint->name,
+ checkpoint->timestamp,
+ NULL,
+ NULL);
+ ep_rt_execution_checkpoint_array_iterator_next (&execution_checkpoints_iterator);
+ }
+ }
+
+ FireEtwDCEndInit_V1 (
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ eventpipe_execute_rundown (
+ fire_domain_rundown_events_func,
+ fire_assembly_rundown_events_func,
+ fire_method_rundown_events_func);
+
+ FireEtwDCEndComplete_V1 (
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+}
+
+bool
+ep_rt_mono_write_event_ee_startup_start (void)
+{
+ return FireEtwEEStartupStart_V1 (
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+}
+
+bool
+ep_rt_mono_write_event_jit_start (MonoMethod *method)
+{
+ if (!EventEnabledMethodJittingStarted_V1 ())
+ return true;
+
+ //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
+ if (method) {
+ uint64_t method_id = 0;
+ uint64_t module_id = 0;
+ uint32_t code_size = 0;
+ uint32_t method_token = 0;
+ char *method_namespace = NULL;
+ const char *method_name = NULL;
+ char *method_signature = NULL;
+
+ //TODO: SendMethodDetailsEvent
+
+ method_id = (uint64_t)method;
+
+ if (!method->dynamic)
+ method_token = method->token;
+
+ if (!mono_method_has_no_body (method)) {
+ ERROR_DECL (error);
+ MonoMethodHeader *header = mono_method_get_header_internal (method, error);
+ if (header)
+ code_size = header->code_size;
+ }
+
+ method_name = method->name;
+ method_signature = mono_signature_full_name (method->signature);
+
+ if (method->klass) {
+ module_id = (uint64_t)m_class_get_image (method->klass);
+ method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+ }
+
+ FireEtwMethodJittingStarted_V1 (
+ method_id,
+ module_id,
+ method_token,
+ code_size,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ g_free (method_namespace);
+ g_free (method_signature);
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_method_il_to_native_map (
+ MonoMethod *method,
+ MonoJitInfo *ji)
+{
+ if (!EventEnabledMethodILToNativeMap ())
+ return true;
+
+ if (method) {
+ // Under netcore we only have root domain.
+ MonoDomain *root_domain = mono_get_root_domain ();
+
+ uint64_t method_id = (uint64_t)method;
+ uint32_t fixed_buffer [64];
+ uint8_t *buffer = NULL;
+
+ uint16_t offset_entries = 0;
+ uint32_t *il_offsets = NULL;
+ uint32_t *native_offsets = NULL;
+
+ MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, root_domain) : NULL;
+ if (debug_info) {
+ if (offset_entries != 0) {
+ offset_entries = debug_info->num_line_numbers;
+ size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
+ if (needed_size > sizeof (fixed_buffer)) {
+ buffer = g_new (uint8_t, needed_size);
+ il_offsets = (uint32_t*)buffer;
+ } else {
+ il_offsets = fixed_buffer;
+ }
+ if (il_offsets) {
+ native_offsets = il_offsets + offset_entries;
+ for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
+ il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
+ native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ }
+ }
+ }
+
+ mono_debug_free_method_jit_info (debug_info);
+ }
+
+ if (!il_offsets && !native_offsets) {
+ // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
+ EP_ASSERT (sizeof (fixed_buffer) >= sizeof (uint32_t) * 2);
+ offset_entries = 1;
+ il_offsets = fixed_buffer;
+ native_offsets = il_offsets + offset_entries;
+ il_offsets [0] = 0;
+ native_offsets [0] = ji ? (uint32_t)ji->code_size : 0;
+ }
+
+ FireEtwMethodILToNativeMap (
+ method_id,
+ 0,
+ 0,
+ offset_entries,
+ il_offsets,
+ native_offsets,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ g_free (buffer);
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_method_load (
+ MonoMethod *method,
+ MonoJitInfo *ji)
+{
+ if (!EventEnabledMethodLoad_V1 () && !EventEnabledMethodLoadVerbose_V1())
+ return true;
+
+ //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
+ if (method) {
+ uint64_t method_id = 0;
+ uint64_t module_id = 0;
+ uint64_t method_code_start = ji ? (uint64_t)ji->code_start : 0;
+ uint32_t method_code_size = ji ? (uint32_t)ji->code_size : 0;
+ uint32_t method_token = 0;
+ uint32_t method_flags = 0;
+ uint8_t kind = MONO_CLASS_DEF;
+ char *method_namespace = NULL;
+ const char *method_name = NULL;
+ char *method_signature = NULL;
+ bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE);
+
+ method_id = (uint64_t)method;
+
+ if (!method->dynamic)
+ method_token = method->token;
+
+ if (ji && mono_jit_info_get_generic_sharing_context (ji)) {
+ method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
+ verbose = true;
+ }
+
+ if (method->dynamic) {
+ method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
+ verbose = true;
+ }
+
+ if (ji && !ji->from_aot && !ji->from_llvm) {
+ method_flags |= METHOD_FLAGS_JITTED_METHOD;
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
+ }
+
+ if (method->is_generic || method->is_inflated) {
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+ verbose = true;
+ }
+
+ if (method->klass) {
+ module_id = (uint64_t)m_class_get_image (method->klass);
+ kind = m_class_get_class_kind (method->klass);
+ if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+ }
+
+ //TODO: SendMethodDetailsEvent
+
+ if (verbose) {
+ method_name = method->name;
+ method_signature = mono_signature_full_name (method->signature);
+
+ if (method->klass)
+ method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+
+ FireEtwMethodLoadVerbose_V1 (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ if (ji && (ji->from_aot || ji->from_llvm))
+ FireEtwMethodLoadVerbose_V1 (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+ } else {
+ FireEtwMethodLoad_V1 (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ if (ji && (ji->from_aot || ji->from_llvm))
+ FireEtwMethodLoad_V1 (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+ }
+
+ g_free (method_namespace);
+ g_free (method_signature);
+ }
+
+ return true;
+}
+
+static
+bool
+get_module_event_data (
+ MonoImage *image,
+ ModuleEventData *module_data)
+{
+ if (image && module_data) {
+ memset (module_data->signature, 0, EP_GUID_SIZE);
+
+ // Under netcore we only have root domain.
+ MonoDomain *root_domain = mono_get_root_domain ();
+
+ module_data->domain_id = (uint64_t)root_domain;
+ module_data->module_id = (uint64_t)image;
+ module_data->assembly_id = (uint64_t)image->assembly;
+
+ // TODO: Extract all module IL/Native paths and pdb metadata when available.
+ module_data->module_il_path = "";
+ module_data->module_il_pdb_path = "";
+ module_data->module_native_path = "";
+ module_data->module_native_pdb_path = "";
+
+ module_data->module_il_pdb_age = 0;
+ module_data->module_native_pdb_age = 0;
+
+ module_data->reserved_flags = 0;
+
+ // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
+ module_data->module_flags = MODULE_FLAGS_MANIFEST_MODULE;
+ if (image->dynamic)
+ module_data->module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
+ if (image->aot_module)
+ module_data->module_flags |= MODULE_FLAGS_NATIVE_MODULE;
+
+ module_data->module_il_path = image->filename ? image->filename : "";
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_module_load (MonoImage *image)
+{
+ if (!EventEnabledModuleLoad_V2 () && !EventEnabledDomainModuleLoad_V1())
+ return true;
- switch (frame->type) {
- case FRAME_TYPE_DEBUGGER_INVOKE:
- case FRAME_TYPE_MANAGED_TO_NATIVE:
- case FRAME_TYPE_TRAMPOLINE:
- case FRAME_TYPE_INTERP_TO_MANAGED:
- case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
- case FRAME_TYPE_INTERP_ENTRY:
- stack_walk_data->top_frame = false;
- return FALSE;
- case FRAME_TYPE_JIT_ENTRY:
- // Frame in JIT compiler at top of callstack, add phantom frame representing call into JIT compiler.
- // Makes it possible to detect stacks waiting on JIT compiler.
- if (_ep_rt_mono_runtime_helper_compile_method && stack_walk_data->top_frame)
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_runtime_helper_compile_method), _ep_rt_mono_runtime_helper_compile_method);
- stack_walk_data->top_frame = false;
- return FALSE;
- case FRAME_TYPE_MANAGED:
- case FRAME_TYPE_INTERP:
- if (frame->ji) {
- stack_walk_data->async_frame |= frame->ji->async;
- MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
- if (method && m_method_is_wrapper (method)) {
- WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
- if (in_safe_point_frame (stack_walk_data->stack_contents, wrapper)) {
- stack_walk_data->safe_point_frame = true;
- }else if (in_runtime_invoke_frame (stack_walk_data->stack_contents, wrapper)) {
- stack_walk_data->runtime_invoke_frame = true;
- } else if (_ep_rt_mono_monitor_enter_method && in_monitor_enter_frame (wrapper)) {
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_method), _ep_rt_mono_monitor_enter_method);
- } else if (_ep_rt_mono_monitor_enter_v4_method && in_monitor_enter_v4_frame (wrapper)) {
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_v4_method), _ep_rt_mono_monitor_enter_v4_method);
- } else if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) {
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
- }
- } else if (method && !m_method_is_wrapper (method)) {
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
- } else if (!method && frame->ji->async && !frame->ji->is_trampoline) {
- ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start), method);
- }
+ if (image) {
+ ModuleEventData module_data;
+ if (get_module_event_data (image, &module_data)) {
+ FireEtwModuleLoad_V2 (
+ module_data.module_id,
+ module_data.assembly_id,
+ module_data.module_flags,
+ module_data.reserved_flags,
+ module_data.module_il_path,
+ module_data.module_native_path,
+ clr_instance_get_id (),
+ module_data.signature,
+ module_data.module_il_pdb_age,
+ module_data.module_il_pdb_path,
+ module_data.signature,
+ module_data.module_native_pdb_age,
+ module_data.module_native_pdb_path,
+ NULL,
+ NULL);
+
+ FireEtwDomainModuleLoad_V1 (
+ module_data.module_id,
+ module_data.assembly_id,
+ module_data.domain_id,
+ module_data.module_flags,
+ module_data.reserved_flags,
+ module_data.module_il_path,
+ module_data.module_native_path,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
}
- stack_walk_data->top_frame = false;
- return ep_stack_contents_get_length (stack_walk_data->stack_contents) >= EP_MAX_STACK_DEPTH;
- default:
- EP_UNREACHABLE ("eventpipe_walk_managed_stack_for_thread");
- return FALSE;
}
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_module_unload (MonoImage *image)
+{
+ if (!EventEnabledModuleUnload_V2())
+ return true;
+
+ if (image) {
+ ModuleEventData module_data;
+ if (get_module_event_data (image, &module_data)) {
+ FireEtwModuleUnload_V2 (
+ module_data.module_id,
+ module_data.assembly_id,
+ module_data.module_flags,
+ module_data.reserved_flags,
+ module_data.module_il_path,
+ module_data.module_native_path,
+ clr_instance_get_id (),
+ module_data.signature,
+ module_data.module_il_pdb_age,
+ module_data.module_il_pdb_path,
+ module_data.signature,
+ module_data.module_native_pdb_age,
+ module_data.module_native_pdb_path,
+ NULL,
+ NULL);
+ }
+ }
+
+ return true;
+}
+
+static
+bool
+get_assembly_event_data (
+ MonoAssembly *assembly,
+ AssemblyEventData *assembly_data)
+{
+ if (assembly && assembly_data) {
+ // Under netcore we only have root domain.
+ MonoDomain *root_domain = mono_get_root_domain ();
+
+ assembly_data->domain_id = (uint64_t)root_domain;
+ assembly_data->assembly_id = (uint64_t)assembly;
+ assembly_data->binding_id = 0;
+
+ assembly_data->assembly_flags = 0;
+ if (assembly->dynamic)
+ assembly_data->assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
+
+ if (assembly->image && assembly->image->aot_module)
+ assembly_data->assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
+
+ assembly_data->assembly_name = mono_stringify_assembly_name (&assembly->aname);
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly)
+{
+ if (!EventEnabledAssemblyLoad_V1 ())
+ return true;
+
+ if (assembly) {
+ AssemblyEventData assembly_data;
+ if (get_assembly_event_data (assembly, &assembly_data)) {
+ FireEtwAssemblyLoad_V1 (
+ assembly_data.assembly_id,
+ assembly_data.domain_id,
+ assembly_data.binding_id,
+ assembly_data.assembly_flags,
+ assembly_data.assembly_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ g_free (assembly_data.assembly_name);
+ }
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_assembly_unload (MonoAssembly *assembly)
+{
+ if (!EventEnabledAssemblyUnload_V1 ())
+ return true;
+
+ if (assembly) {
+ AssemblyEventData assembly_data;
+ if (get_assembly_event_data (assembly, &assembly_data)) {
+ FireEtwAssemblyUnload_V1 (
+ assembly_data.assembly_id,
+ assembly_data.domain_id,
+ assembly_data.binding_id,
+ assembly_data.assembly_flags,
+ assembly_data.assembly_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ g_free (assembly_data.assembly_name);
+ }
+ }
+
+ return true;
+}
+
+bool
+ep_rt_mono_write_event_thread_created (ep_rt_thread_id_t tid)
+{
+ if (!EventEnabledThreadCreated ())
+ return true;
+
+ uint64_t managed_thread = 0;
+ uint64_t native_thread_id = ep_rt_thread_id_t_to_uint64_t (tid);
+ uint64_t managed_thread_id = 0;
+ uint32_t flags = 0;
+
+ MonoThread *thread = mono_thread_current ();
+ if (thread && mono_thread_info_get_tid (thread->thread_info) == tid) {
+ managed_thread_id = (uint64_t)mono_thread_get_managed_id (thread);
+ managed_thread = (uint64_t)thread;
+
+ switch (mono_thread_info_get_flags (thread->thread_info)) {
+ case MONO_THREAD_INFO_FLAGS_NO_GC:
+ case MONO_THREAD_INFO_FLAGS_NO_SAMPLE:
+ flags |= THREAD_FLAGS_GC_SPECIAL;
+ }
+
+ if (mono_gc_is_finalizer_thread (thread))
+ flags |= THREAD_FLAGS_FINALIZER;
+
+ if (thread->threadpool_thread)
+ flags |= THREAD_FLAGS_THREADPOOL_WORKER;
+ }
+
+ FireEtwThreadCreated (
+ managed_thread,
+ (uint64_t)mono_get_root_domain (),
+ flags,
+ managed_thread_id,
+ native_thread_id,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ return true;
}
-static
-gboolean
-eventpipe_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- void *data)
+bool
+ep_rt_mono_write_event_thread_terminated (ep_rt_thread_id_t tid)
{
- return eventpipe_walk_managed_stack_for_thread (frame, ctx, (EventPipeStackWalkData *)data);
+ if (!EventEnabledThreadTerminated ())
+ return true;
+
+ uint64_t managed_thread = 0;
+ MonoThread *thread = mono_thread_current ();
+ if (thread && mono_thread_info_get_tid (thread->thread_info) == tid)
+ managed_thread = (uint64_t)thread;
+
+ FireEtwThreadTerminated (
+ managed_thread,
+ (uint64_t)mono_get_root_domain (),
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ return true;
}
static
-gboolean
-eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- void *data)
+uint32_t
+get_type_start_id (MonoType *type)
{
- EP_ASSERT (frame != NULL);
- EP_ASSERT (data != NULL);
+ uint32_t start_id = (uint32_t)(uintptr_t)type;
- EventPipeSampleProfileStackWalkData *sample_data = (EventPipeSampleProfileStackWalkData *)data;
+ start_id = (((start_id * 215497) >> 16) ^ ((start_id * 1823231) + start_id));
- if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
- switch (frame->type) {
- case FRAME_TYPE_MANAGED:
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- break;
- case FRAME_TYPE_MANAGED_TO_NATIVE:
- case FRAME_TYPE_TRAMPOLINE:
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
- break;
- case FRAME_TYPE_JIT_ENTRY:
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
- break;
- case FRAME_TYPE_INTERP:
- sample_data->payload_data = frame->managed ? EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED : EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
- break;
- case FRAME_TYPE_INTERP_TO_MANAGED:
- case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
- break;
- default:
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- }
- }
+ // Mix in highest bits on 64-bit systems only
+ if (sizeof (type) > 4)
+ start_id = start_id ^ (((uint64_t)type >> 31) >> 1);
- return eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_walk_data);
+ return start_id;
}
-static
-void
-profiler_eventpipe_thread_exited (
- MonoProfiler *prof,
- uintptr_t tid)
+bool
+ep_rt_mono_write_event_type_load_start (MonoType *type)
{
- void ep_rt_mono_thread_exited (void);
- ep_rt_mono_thread_exited ();
+ if (!EventEnabledTypeLoadStart ())
+ return true;
+
+ FireEtwTypeLoadStart (
+ get_type_start_id (type),
+ clr_instance_get_id (),
+ NULL,
+ NULL);
+
+ return true;
}
-void
-ep_rt_mono_init (void)
+bool
+ep_rt_mono_write_event_type_load_stop (MonoType *type)
{
- mono_native_tls_alloc (&_ep_rt_mono_thread_holder_tls_id, NULL);
+ if (!EventEnabledTypeLoadStop ())
+ return true;
- mono_100ns_ticks ();
- mono_rand_open ();
- _ep_rt_mono_rand_provider = mono_rand_init (NULL, 0);
+ char *type_name = NULL;
+ if (type)
+ type_name = mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
- _ep_rt_mono_initialized = TRUE;
+ FireEtwTypeLoadStop (
+ get_type_start_id (type),
+ clr_instance_get_id (),
+ 6 /* CLASS_LOADED */,
+ (uint64_t)type,
+ type_name,
+ NULL,
+ NULL);
- _ep_rt_mono_profiler = mono_profiler_create (NULL);
- mono_profiler_set_thread_stopped_callback (_ep_rt_mono_profiler, profiler_eventpipe_thread_exited);
+ g_free (type_name);
- MonoMethodSignature *method_signature = mono_metadata_signature_alloc (mono_get_corlib (), 1);
- if (method_signature) {
- method_signature->params[0] = m_class_get_byval_arg (mono_get_object_class());
- method_signature->ret = m_class_get_byval_arg (mono_get_void_class());
+ return true;
+}
+
+static
+gboolean
+get_exception_ip_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data)
+{
+ *(uintptr_t *)data = (uintptr_t)MONO_CONTEXT_GET_IP (ctx);
+ return TRUE;
+}
+
+bool
+ep_rt_mono_write_event_exception_thrown (MonoObject *obj)
+{
+ if (!EventEnabledExceptionThrown_V1 ())
+ return true;
+ if (obj) {
ERROR_DECL (error);
- MonoClass *runtime_helpers = mono_class_from_name_checked (mono_get_corlib (), "System.Runtime.CompilerServices", "RuntimeHelpers", error);
- if (is_ok (error) && runtime_helpers) {
- MonoMethodBuilder *method_builder = mono_mb_new (runtime_helpers, "CompileMethod", MONO_WRAPPER_RUNTIME_INVOKE);
- if (method_builder) {
- _ep_rt_mono_runtime_helper_compile_method = mono_mb_create_method (method_builder, method_signature, 1);
- mono_mb_free (method_builder);
- }
- }
- mono_error_cleanup (error);
- mono_metadata_free_method_signature (method_signature);
+ char *type_name = NULL;
+ char *exception_message = NULL;
+ uint16_t flags = 0;
+ uint32_t hresult = 0;
+ uintptr_t ip = 0;
- _ep_rt_mono_runtime_helper_compile_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
- if (_ep_rt_mono_runtime_helper_compile_method) {
- _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_runtime_helper_compile_method);
- _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_size = 20;
- _ep_rt_mono_runtime_helper_compile_method_jitinfo->d.method = _ep_rt_mono_runtime_helper_compile_method;
+ if (mono_object_isinst_checked ((MonoObject *) obj, mono_get_exception_class (), error)) {
+ MonoException *exception = (MonoException *)obj;
+ flags |= EXCEPTION_THROWN_FLAGS_IS_CLS_COMPLIANT;
+ if (exception->inner_ex)
+ flags |= EXCEPTION_THROWN_FLAGS_HAS_INNER;
+ exception_message = ep_rt_utf16_to_utf8_string (mono_string_chars_internal (exception->message), mono_string_length_internal (exception->message));
+ hresult = exception->hresult;
}
- }
- {
- ERROR_DECL (error);
- MonoMethodDesc *desc = NULL;
- MonoClass *monitor = mono_class_from_name_checked (mono_get_corlib (), "System.Threading", "Monitor", error);
- if (is_ok (error) && monitor) {
- desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
- if (desc) {
- _ep_rt_mono_monitor_enter_v4_method = mono_method_desc_search_in_class (desc, monitor);
- mono_method_desc_free (desc);
+ if (mono_get_eh_callbacks ()->mono_walk_stack_with_ctx)
+ mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (get_exception_ip_func, NULL, MONO_UNWIND_SIGNAL_SAFE, (void *)&ip);
- _ep_rt_mono_monitor_enter_v4_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
- if (_ep_rt_mono_monitor_enter_v4_method_jitinfo) {
- _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_v4_method);
- _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_size = 20;
- _ep_rt_mono_monitor_enter_v4_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_v4_method;
- }
- }
+ type_name = mono_type_get_name_full (m_class_get_byval_arg (mono_object_class (obj)), MONO_TYPE_NAME_FORMAT_IL);
- desc = mono_method_desc_new ("Monitor:Enter(object)", FALSE);
- if (desc) {
- _ep_rt_mono_monitor_enter_method = mono_method_desc_search_in_class (desc, monitor);
- mono_method_desc_free (desc);
+ FireEtwExceptionThrown_V1 (
+ type_name,
+ exception_message,
+ (void *)&ip,
+ hresult,
+ flags,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
- _ep_rt_mono_monitor_enter_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
- if (_ep_rt_mono_monitor_enter_method_jitinfo) {
- _ep_rt_mono_monitor_enter_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_method);
- _ep_rt_mono_monitor_enter_method_jitinfo->code_size = 20;
- _ep_rt_mono_monitor_enter_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_method;
- }
- }
+ if (!mono_component_profiler_clauses_enabled ()) {
+ FireEtwExceptionThrownStop (
+ NULL,
+ NULL);
}
- mono_error_cleanup (error);
- }
-}
-
-void
-ep_rt_mono_init_finish (void)
-{
- if (mono_runtime_get_no_exec ())
- return;
- // Managed init of diagnostics classes, like registration of RuntimeEventSource (if available).
- ERROR_DECL (error);
+ g_free (exception_message);
+ g_free (type_name);
- MonoClass *runtime_event_source = mono_class_from_name_checked (mono_get_corlib (), "System.Diagnostics.Tracing", "RuntimeEventSource", error);
- if (is_ok (error) && runtime_event_source) {
- MonoMethod *init = mono_class_get_method_from_name_checked (runtime_event_source, "Initialize", -1, 0, error);
- if (is_ok (error) && init) {
- mono_runtime_try_invoke_handle (init, NULL_HANDLE, NULL, error);
- }
+ mono_error_cleanup (error);
}
- mono_error_cleanup (error);
+ return true;
}
-void
-ep_rt_mono_fini (void)
+bool
+ep_rt_mono_write_event_exception_clause (
+ MonoMethod *method,
+ uint32_t clause_num,
+ MonoExceptionEnum clause_type,
+ MonoObject *obj)
{
- if (_ep_rt_mono_sampled_thread_callstacks)
- g_array_free (_ep_rt_mono_sampled_thread_callstacks, TRUE);
-
- if (_ep_rt_mono_initialized)
- mono_rand_close (_ep_rt_mono_rand_provider);
+ if (!mono_component_profiler_clauses_enabled ())
+ return true;
- g_free (_ep_rt_mono_runtime_helper_compile_method_jitinfo);
- _ep_rt_mono_runtime_helper_compile_method_jitinfo = NULL;
+ if ((clause_type == MONO_EXCEPTION_CLAUSE_FAULT || clause_type == MONO_EXCEPTION_CLAUSE_NONE) && (!EventEnabledExceptionCatchStart() || !EventEnabledExceptionCatchStop()))
+ return true;
- mono_free_method (_ep_rt_mono_runtime_helper_compile_method);
- _ep_rt_mono_runtime_helper_compile_method = NULL;
+ if (clause_type == MONO_EXCEPTION_CLAUSE_FILTER && (!EventEnabledExceptionFilterStart() || !EventEnabledExceptionFilterStop()))
+ return true;
- g_free (_ep_rt_mono_monitor_enter_method_jitinfo);
- _ep_rt_mono_monitor_enter_method_jitinfo = NULL;
- _ep_rt_mono_monitor_enter_method = NULL;
+ if (clause_type == MONO_EXCEPTION_CLAUSE_FINALLY && (!EventEnabledExceptionFinallyStart() || !EventEnabledExceptionFinallyStop()))
+ return true;
- g_free (_ep_rt_mono_monitor_enter_v4_method_jitinfo);
- _ep_rt_mono_monitor_enter_v4_method_jitinfo = NULL;
- _ep_rt_mono_monitor_enter_v4_method = NULL;
+ uintptr_t ip = 0; //TODO: Have profiler pass along IP of handler block.
+ uint64_t method_id = (uint64_t)method;
+ char *method_name = NULL;
- _ep_rt_mono_sampled_thread_callstacks = NULL;
- _ep_rt_mono_rand_provider = NULL;
- _ep_rt_mono_initialized = FALSE;
-}
+ method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
-bool
-ep_rt_mono_rand_try_get_bytes (
- uint8_t *buffer,
- size_t buffer_size)
-{
- EP_ASSERT (_ep_rt_mono_rand_provider != NULL);
+ if ((clause_type == MONO_EXCEPTION_CLAUSE_FAULT || clause_type == MONO_EXCEPTION_CLAUSE_NONE)) {
+ FireEtwExceptionCatchStart (
+ (uint64_t)ip,
+ method_id,
+ (const ep_char8_t *)method_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
- ERROR_DECL (error);
- return mono_rand_try_get_bytes (&_ep_rt_mono_rand_provider, (guchar *)buffer, (gssize)buffer_size, error);
-}
+ FireEtwExceptionCatchStop (
+ NULL,
+ NULL);
-EventPipeThread *
-ep_rt_mono_thread_get_or_create (void)
-{
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
- if (!thread_holder) {
- thread_holder = thread_holder_alloc_func ();
- mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, thread_holder);
+ FireEtwExceptionThrownStop (
+ NULL,
+ NULL);
}
- return ep_thread_holder_get_thread (thread_holder);
-}
-void *
-ep_rt_mono_thread_attach (bool background_thread)
-{
- MonoThread *thread = NULL;
+ if (clause_type == MONO_EXCEPTION_CLAUSE_FILTER) {
+ FireEtwExceptionFilterStart (
+ (uint64_t)ip,
+ method_id,
+ (const ep_char8_t *)method_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
- // NOTE, under netcore, only root domain exists.
- if (!mono_thread_current ()) {
- thread = mono_thread_internal_attach (mono_get_root_domain ());
- if (background_thread && thread) {
- mono_thread_set_state (thread, ThreadState_Background);
- mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
- }
+ FireEtwExceptionFilterStop (
+ NULL,
+ NULL);
}
- return thread;
-}
+ if (clause_type == MONO_EXCEPTION_CLAUSE_FINALLY) {
+ FireEtwExceptionFinallyStart (
+ (uint64_t)ip,
+ method_id,
+ (const ep_char8_t *)method_name,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
-void *
-ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type)
-{
- void *result = ep_rt_mono_thread_attach (background_thread);
- if (result && thread_type == EP_THREAD_TYPE_SAMPLING) {
- // Increase sampling thread priority, accepting failures.
-#ifdef HOST_WIN32
- SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
-#elif _POSIX_PRIORITY_SCHEDULING
- int policy;
- int priority;
- struct sched_param param;
- int schedparam_result = pthread_getschedparam (pthread_self (), &policy, ¶m);
- if (schedparam_result == 0) {
- // Attempt to switch the thread to real time scheduling. This will not
- // necessarily work on all OSs; for example, most Linux systems will give
- // us EPERM here unless configured to allow this.
- priority = param.sched_priority;
- param.sched_priority = sched_get_priority_max (SCHED_RR);
- if (param.sched_priority != -1) {
- schedparam_result = pthread_setschedparam (pthread_self (), SCHED_RR, ¶m);
- if (schedparam_result != 0) {
- // Fallback, attempt to increase to max priority using current policy.
- param.sched_priority = sched_get_priority_max (policy);
- if (param.sched_priority != -1 && param.sched_priority != priority)
- pthread_setschedparam (pthread_self (), policy, ¶m);
- }
- }
- }
-#endif
+ FireEtwExceptionFinallyStop (
+ NULL,
+ NULL);
}
- return result;
+ g_free (method_name);
+ return true;
}
-void
-ep_rt_mono_thread_detach (void)
+bool
+ep_rt_mono_write_event_monitor_contention_start (MonoObject *obj)
{
- MonoThread *current_thread = mono_thread_current ();
- if (current_thread)
- mono_thread_internal_detach (current_thread);
-}
+ if (!EventEnabledContentionStart_V1 ())
+ return true;
-void
-ep_rt_mono_thread_exited (void)
-{
- if (_ep_rt_mono_initialized) {
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
- if (thread_holder)
- thread_holder_free_func (thread_holder);
- mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, NULL);
- }
-}
+ FireEtwContentionStart_V1 (
+ 0 /* ManagedContention */,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
-#ifdef HOST_WIN32
-int64_t
-ep_rt_mono_perf_counter_query (void)
-{
- LARGE_INTEGER value;
- if (QueryPerformanceCounter (&value))
- return (int64_t)value.QuadPart;
- else
- return 0;
+ return true;
}
-int64_t
-ep_rt_mono_perf_frequency_query (void)
+bool
+ep_rt_mono_write_event_monitor_contention_stop (MonoObject *obj)
{
- LARGE_INTEGER value;
- if (QueryPerformanceFrequency (&value))
- return (int64_t)value.QuadPart;
- else
- return 0;
-}
+ if (!EventEnabledContentionStop ())
+ return true;
-void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
-{
- SYSTEMTIME value;
- GetSystemTime (&value);
+ FireEtwContentionStop (
+ 0 /* ManagedContention */,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
- EP_ASSERT (system_time != NULL);
- ep_system_time_set (
- system_time,
- value.wYear,
- value.wMonth,
- value.wDayOfWeek,
- value.wDay,
- value.wHour,
- value.wMinute,
- value.wSecond,
- value.wMilliseconds);
+ return true;
}
-int64_t
-ep_rt_mono_system_timestamp_get (void)
+bool
+ep_rt_mono_write_event_method_jit_memory_allocated_for_code (
+ const uint8_t *buffer,
+ uint64_t size,
+ MonoProfilerCodeBufferType type,
+ const void *data)
{
- FILETIME value;
- GetSystemTimeAsFileTime (&value);
- return (int64_t)((((uint64_t)value.dwHighDateTime) << 32) | (uint64_t)value.dwLowDateTime);
-}
-#else
-#include
-#include
-#include
-#include
-
-#if HAVE_SYS_TIME_H
-#include
-#endif // HAVE_SYS_TIME_H
-
-#if HAVE_MACH_ABSOLUTE_TIME
-#include
-static mono_lazy_init_t _ep_rt_mono_time_base_info_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
-static mach_timebase_info_data_t _ep_rt_mono_time_base_info = {0};
-#endif
+ if (!EventEnabledMethodJitMemoryAllocatedForCode ())
+ return true;
-#ifdef HAVE_LOCALTIME_R
-#define HAVE_GMTIME_R 1
-#endif
+ if (type != MONO_PROFILER_CODE_BUFFER_METHOD)
+ return true;
-static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL;
-static const int64_t SECS_TO_100NS = 10000000;
-static const int64_t SECS_TO_NS = 1000000000;
-static const int64_t MSECS_TO_MIS = 1000;
+ uint64_t method_id = 0;
+ uint64_t module_id = 0;
-/* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */
-#if defined (HAVE_CLOCK_MONOTONIC) && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))
-#undef HAVE_CLOCK_MONOTONIC
-#endif
+ if (data) {
+ MonoMethod *method;
+ method = (MonoMethod *)data;
+ method_id = (uint64_t)method;
+ if (method->klass)
+ module_id = (uint64_t)(uint64_t)m_class_get_image (method->klass);
+ }
-#ifndef HAVE_CLOCK_MONOTONIC
-static const int64_t MISECS_TO_NS = 1000;
-#endif
+ FireEtwMethodJitMemoryAllocatedForCode (
+ method_id,
+ module_id,
+ size,
+ 0,
+ size,
+ 0 /* CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN */,
+ clr_instance_get_id (),
+ NULL,
+ NULL);
-static
-void
-time_base_info_lazy_init (void);
+ return true;
+}
-static
-int64_t
-system_time_to_int64 (
- time_t sec,
- long nsec);
+bool
+ep_rt_write_event_threadpool_worker_thread_start (
+ uint32_t active_thread_count,
+ uint32_t retired_worker_thread_count,
+ uint16_t clr_instance_id)
+{
+ return FireEtwThreadPoolWorkerThreadStart (
+ active_thread_count,
+ retired_worker_thread_count,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
+}
-#if HAVE_MACH_ABSOLUTE_TIME
-static
-void
-time_base_info_lazy_init (void)
+bool
+ep_rt_write_event_threadpool_worker_thread_stop (
+ uint32_t active_thread_count,
+ uint32_t retired_worker_thread_count,
+ uint16_t clr_instance_id)
{
- kern_return_t result = mach_timebase_info (&_ep_rt_mono_time_base_info);
- if (result != KERN_SUCCESS)
- memset (&_ep_rt_mono_time_base_info, 0, sizeof (_ep_rt_mono_time_base_info));
+ return FireEtwThreadPoolWorkerThreadStop (
+ active_thread_count,
+ retired_worker_thread_count,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-#endif
-int64_t
-ep_rt_mono_perf_counter_query (void)
+bool
+ep_rt_write_event_threadpool_worker_thread_wait (
+ uint32_t active_thread_count,
+ uint32_t retired_worker_thread_count,
+ uint16_t clr_instance_id)
{
-#if HAVE_MACH_ABSOLUTE_TIME
- return (int64_t)mach_absolute_time ();
-#elif HAVE_CLOCK_MONOTONIC
- struct timespec ts;
- int result = clock_gettime (CLOCK_MONOTONIC, &ts);
- if (result == 0)
- return ((int64_t)(ts.tv_sec) * (int64_t)(SECS_TO_NS)) + (int64_t)(ts.tv_nsec);
-#else
- #error "ep_rt_mono_perf_counter_get requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
-#endif
- return 0;
+ return FireEtwThreadPoolWorkerThreadWait (
+ active_thread_count,
+ retired_worker_thread_count,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-int64_t
-ep_rt_mono_perf_frequency_query (void)
+bool
+ep_rt_write_event_threadpool_worker_thread_adjustment_sample (
+ double throughput,
+ uint16_t clr_instance_id)
{
-#if HAVE_MACH_ABSOLUTE_TIME
- // (numer / denom) gives you the nanoseconds per tick, so the below code
- // computes the number of ticks per second. We explicitly do the multiplication
- // first in order to help minimize the error that is produced by integer division.
- mono_lazy_initialize (&_ep_rt_mono_time_base_info_init, time_base_info_lazy_init);
- if (_ep_rt_mono_time_base_info.denom == 0 || _ep_rt_mono_time_base_info.numer == 0)
- return 0;
- return ((int64_t)(SECS_TO_NS) * (int64_t)(_ep_rt_mono_time_base_info.denom)) / (int64_t)(_ep_rt_mono_time_base_info.numer);
-#elif HAVE_CLOCK_MONOTONIC
- // clock_gettime () returns a result in terms of nanoseconds rather than a count. This
- // means that we need to either always scale the result by the actual resolution (to
- // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer
- // the latter since it allows the highest throughput and should minimize error propagated
- // to the user.
- return (int64_t)(SECS_TO_NS);
-#else
- #error "ep_rt_mono_perf_frequency_query requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
-#endif
- return 0;
+ return FireEtwThreadPoolWorkerThreadAdjustmentSample (
+ throughput,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
+bool
+ep_rt_write_event_threadpool_worker_thread_adjustment_adjustment (
+ double average_throughput,
+ uint32_t networker_thread_count,
+ /*NativeRuntimeEventSource.ThreadAdjustmentReasonMap*/ int32_t reason,
+ uint16_t clr_instance_id)
{
- time_t tt;
-#if HAVE_GMTIME_R
- struct tm ut;
-#endif /* HAVE_GMTIME_R */
- struct tm *ut_ptr;
- struct timeval time_val;
- int timeofday_retval;
-
- EP_ASSERT (system_time != NULL);
-
- tt = time (NULL);
-
- /* We can't get millisecond resolution from time (), so we get it from gettimeofday () */
- timeofday_retval = gettimeofday (&time_val, NULL);
-
-#if HAVE_GMTIME_R
- ut_ptr = &ut;
- if (gmtime_r (&tt, ut_ptr) == NULL)
-#else /* HAVE_GMTIME_R */
- if ((ut_ptr = gmtime (&tt)) == NULL)
-#endif /* HAVE_GMTIME_R */
- EP_UNREACHABLE ();
-
- uint16_t milliseconds = 0;
- if (timeofday_retval != -1) {
- int old_seconds;
- int new_seconds;
-
- milliseconds = time_val.tv_usec / MSECS_TO_MIS;
-
- old_seconds = ut_ptr->tm_sec;
- new_seconds = time_val.tv_sec % 60;
-
- /* just in case we reached the next second in the interval between time () and gettimeofday () */
- if (old_seconds != new_seconds)
- milliseconds = 999;
- }
+ return FireEtwThreadPoolWorkerThreadAdjustmentAdjustment (
+ average_throughput,
+ networker_thread_count,
+ reason,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
+}
- ep_system_time_set (
- system_time,
- 1900 + ut_ptr->tm_year,
- ut_ptr->tm_mon + 1,
- ut_ptr->tm_wday,
- ut_ptr->tm_mday,
- ut_ptr->tm_hour,
- ut_ptr->tm_min,
- ut_ptr->tm_sec,
- milliseconds);
+bool
+ep_rt_write_event_threadpool_worker_thread_adjustment_stats (
+ double duration,
+ double throughput,
+ double threadpool_worker_thread_wait,
+ double throughput_wave,
+ double throughput_error_estimate,
+ double average_throughput_error_estimate,
+ double throughput_ratio,
+ double confidence,
+ double new_control_setting,
+ uint16_t new_thread_wave_magnitude,
+ uint16_t clr_instance_id)
+{
+ return FireEtwThreadPoolWorkerThreadAdjustmentStats (
+ duration,
+ throughput,
+ threadpool_worker_thread_wait,
+ throughput_wave,
+ throughput_error_estimate,
+ average_throughput_error_estimate,
+ throughput_ratio,
+ confidence,
+ new_control_setting,
+ new_thread_wave_magnitude,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-static
-inline
-int64_t
-system_time_to_int64 (
- time_t sec,
- long nsec)
+bool
+ep_rt_write_event_threadpool_io_enqueue (
+ intptr_t native_overlapped,
+ intptr_t overlapped,
+ bool multi_dequeues,
+ uint16_t clr_instance_id)
{
- return ((int64_t)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + (nsec / 100);
+ return FireEtwThreadPoolIOEnqueue (
+ (const void *)native_overlapped,
+ (const void *)overlapped,
+ multi_dequeues,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-int64_t
-ep_rt_mono_system_timestamp_get (void)
+bool
+ep_rt_write_event_threadpool_io_dequeue (
+ intptr_t native_overlapped,
+ intptr_t overlapped,
+ uint16_t clr_instance_id)
{
-#if HAVE_CLOCK_MONOTONIC
- struct timespec time;
- if (clock_gettime (CLOCK_REALTIME, &time) == 0)
- return system_time_to_int64 (time.tv_sec, time.tv_nsec);
-#else
- struct timeval time;
- if (gettimeofday (&time, NULL) == 0)
- return system_time_to_int64 (time.tv_sec, time.tv_usec * MISECS_TO_NS);
-#endif
- else
- return system_time_to_int64 (0, 0);
+ return FireEtwThreadPoolIODequeue (
+ (const void *)native_overlapped,
+ (const void *)overlapped,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
}
-#endif
-#ifndef HOST_WIN32
-#if defined(__APPLE__)
-#if defined (TARGET_OSX)
-G_BEGIN_DECLS
-gchar ***_NSGetEnviron(void);
-G_END_DECLS
-#define environ (*_NSGetEnviron())
-#else
-static char *_ep_rt_mono_environ[1] = { NULL };
-#define environ _ep_rt_mono_environ
-#endif /* defined (TARGET_OSX) */
-#else
-G_BEGIN_DECLS
-extern char **environ;
-G_END_DECLS
-#endif /* defined (__APPLE__) */
-#endif /* !defined (HOST_WIN32) */
+bool
+ep_rt_write_event_threadpool_working_thread_count (
+ uint16_t count,
+ uint16_t clr_instance_id)
+{
+ return FireEtwThreadPoolWorkingThreadCount (
+ count,
+ clr_instance_id,
+ NULL,
+ NULL) == 0 ? true : false;
+}
+static
void
-ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
+runtime_profiler_jit_begin (
+ MonoProfiler *prof,
+ MonoMethod *method)
{
- EP_ASSERT (env_array != NULL);
-#ifdef HOST_WIN32
- LPWSTR envs = GetEnvironmentStringsW ();
- if (envs) {
- LPWSTR next = envs;
- while (*next) {
- ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (next));
- next += ep_rt_utf16_string_len (next) + 1;
- }
- FreeEnvironmentStringsW (envs);
- }
-#else
- gchar **next = NULL;
- for (next = environ; *next != NULL; ++next)
- ep_rt_env_array_utf16_append (env_array, ep_rt_utf8_to_utf16_string (*next, -1));
-#endif
+ ep_rt_mono_write_event_jit_start (method);
+}
+
+static
+void
+runtime_profiler_jit_failed (
+ MonoProfiler *prof,
+ MonoMethod *method)
+{
+ //TODO: CoreCLR doesn't have this case, so no failure event currently exists.
}
+static
void
-ep_rt_mono_init_providers_and_events (void)
+runtime_profiler_jit_done (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoJitInfo *ji)
{
- extern void InitProvidersAndEvents (void);
- InitProvidersAndEvents ();
+ ep_rt_mono_write_event_method_load (method, ji);
+ ep_rt_mono_write_event_method_il_to_native_map (method, ji);
}
+static
void
-ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config)
+runtime_profiler_image_loaded (
+ MonoProfiler *prof,
+ MonoImage *image)
{
- if (!ep_rt_utf8_string_compare (ep_config_get_rundown_provider_name_utf8 (), ep_provider_config_get_provider_name (provider_config))) {
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = ep_provider_config_get_logging_level (provider_config);
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = ep_provider_config_get_keywords (provider_config);
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = true;
- }
+ if (image && image->heap_pdb.size == 0)
+ ep_rt_mono_write_event_module_load (image);
}
-bool
-ep_rt_mono_providers_validate_all_disabled (void)
+static
+void
+runtime_profiler_image_unloaded (
+ MonoProfiler *prof,
+ MonoImage *image)
{
- return (!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled &&
- !MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled &&
- !MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled);
+ if (image && image->heap_pdb.size == 0)
+ ep_rt_mono_write_event_module_unload (image);
}
+static
void
-ep_rt_mono_fini_providers_and_events (void)
+runtime_profiler_assembly_loaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
{
- // dotnet/runtime: issue 12775: EventPipe shutdown race conditions
- // Deallocating providers/events here might cause AV if a WriteEvent
- // was to occur. Thus, we are not doing this cleanup.
+ ep_rt_mono_write_event_assembly_load (assembly);
}
-bool
-ep_rt_mono_walk_managed_stack_for_thread (
- ep_rt_thread_handle_t thread,
- EventPipeStackContents *stack_contents)
+static
+void
+runtime_profiler_assembly_unloaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
{
- EP_ASSERT (thread != NULL && stack_contents != NULL);
-
- EventPipeStackWalkData stack_walk_data;
- stack_walk_data.stack_contents = stack_contents;
- stack_walk_data.top_frame = true;
- stack_walk_data.async_frame = false;
- stack_walk_data.safe_point_frame = false;
- stack_walk_data.runtime_invoke_frame = false;
-
- if (thread == ep_rt_thread_get_handle () && mono_get_eh_callbacks ()->mono_walk_stack_with_ctx)
- mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
- else if (mono_get_eh_callbacks ()->mono_walk_stack_with_state)
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
-
- return true;
+ ep_rt_mono_write_event_assembly_unload (assembly);
}
-bool
-ep_rt_mono_method_get_simple_assembly_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len)
+static
+void
+runtime_profiler_thread_started (
+ MonoProfiler *prof,
+ uintptr_t tid)
{
- EP_ASSERT (method != NULL);
- EP_ASSERT (name != NULL);
-
- MonoClass *method_class = mono_method_get_class (method);
- MonoImage *method_image = method_class ? mono_class_get_image (method_class) : NULL;
- const ep_char8_t *assembly_name = method_image ? mono_image_get_name (method_image) : NULL;
-
- if (!assembly_name)
- return false;
-
- g_strlcpy (name, assembly_name, name_len);
- return true;
+ ep_rt_mono_write_event_thread_created (ep_rt_uint64_t_to_thread_id_t (tid));
}
-bool
-ep_rt_mono_method_get_full_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len)
+static
+void
+runtime_profiler_thread_stopped (
+ MonoProfiler *prof,
+ uintptr_t tid)
{
- EP_ASSERT (method != NULL);
- EP_ASSERT (name != NULL);
-
- char *full_method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
- if (!full_method_name)
- return false;
-
- g_strlcpy (name, full_method_name, name_len);
-
- g_free (full_method_name);
- return true;
+ ep_rt_mono_write_event_thread_terminated (ep_rt_uint64_t_to_thread_id_t (tid));
}
-bool
-ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
- ep_rt_thread_handle_t sampling_thread,
- EventPipeEvent *sampling_event)
+static
+void
+runtime_profiler_class_loading (
+ MonoProfiler *prof,
+ MonoClass *klass)
{
- // Follows CoreClr implementation of sample profiler. Generic invasive/expensive way to do CPU sample profiling relying on STW and stackwalks.
- // TODO: Investigate alternatives on platforms supporting Signals/SuspendThread (see Mono profiler) or CPU PMU's (see ETW/perf_event_open).
-
- // Sample profiler only runs on one thread, no need to synchorinize.
- if (!_ep_rt_mono_sampled_thread_callstacks)
- _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileStackWalkData), _ep_rt_mono_max_sampled_thread_count);
-
- // Make sure there is room based on previous max number of sampled threads.
- // NOTE, there is a chance there are more threads than max, if that's the case we will
- // miss those threads in this sample, but will be included in next when max has been adjusted.
- g_array_set_size (_ep_rt_mono_sampled_thread_callstacks, _ep_rt_mono_max_sampled_thread_count);
-
- uint32_t filtered_thread_count = 0;
- uint32_t sampled_thread_count = 0;
-
- mono_stop_world (MONO_THREAD_INFO_FLAGS_NO_GC);
-
- gboolean async_context = mono_thread_info_is_async_context ();
- mono_thread_info_set_is_async_context (TRUE);
-
- // Record all info needed in sample events while runtime is suspended, must be async safe.
- FOREACH_THREAD_SAFE_EXCLUDE (thread_info, MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
- if (!mono_thread_info_is_running (thread_info)) {
- MonoThreadUnwindState *thread_state = mono_thread_info_get_suspend_state (thread_info);
- if (thread_state->valid) {
- if (sampled_thread_count < _ep_rt_mono_max_sampled_thread_count) {
- EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, sampled_thread_count);
- data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
- data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
- data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
- data->stack_walk_data.stack_contents = &data->stack_contents;
- data->stack_walk_data.top_frame = true;
- data->stack_walk_data.async_frame = false;
- data->stack_walk_data.safe_point_frame = false;
- data->stack_walk_data.runtime_invoke_frame = false;
- ep_stack_contents_reset (&data->stack_contents);
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
- if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && (data->stack_walk_data.safe_point_frame || data->stack_walk_data.runtime_invoke_frame)) {
- // If classified as external code (managed->native frame on top of stack), but have a safe point or runtime invoke frame
- // as second, re-classify current callstack to be executing managed code.
- data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- }
-
- sampled_thread_count++;
- }
- }
- }
- filtered_thread_count++;
- } FOREACH_THREAD_SAFE_END
-
- mono_thread_info_set_is_async_context (async_context);
- mono_restart_world (MONO_THREAD_INFO_FLAGS_NO_GC);
-
- // Fire sample event for threads. Must be done after runtime is resumed since it's not async safe.
- // Since we can't keep thread info around after runtime as been suspended, use an empty
- // adapter instance and only set recorded tid as parameter inside adapter.
- THREAD_INFO_TYPE adapter = { { 0 } };
- for (uint32_t i = 0; i < sampled_thread_count; ++i) {
- EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, i);
- if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) {
- // Check if we have an async frame, if so we will need to make sure all frames are registered in regular jit info table.
- // TODO: An async frame can contain wrapper methods (no way to check during stackwalk), we could skip writing profile event
- // for this specific stackwalk or we could cleanup stack_frames before writing profile event.
- if (data->stack_walk_data.async_frame) {
- for (int i = 0; i < data->stack_contents.next_available_frame; ++i)
- mono_jit_info_table_find_internal ((gpointer)data->stack_contents.stack_frames [i], TRUE, FALSE);
- }
- mono_thread_info_set_tid (&adapter, ep_rt_uint64_t_to_thread_id_t (data->thread_id));
- ep_write_sample_profile_event (sampling_thread, sampling_event, &adapter, &data->stack_contents, (uint8_t *)&data->payload_data, sizeof (data->payload_data));
- }
- }
-
- // Current thread count will be our next maximum sampled threads.
- _ep_rt_mono_max_sampled_thread_count = filtered_thread_count;
-
- return true;
+ ep_rt_mono_write_event_type_load_start (m_class_get_byval_arg (klass));
}
+static
void
-ep_rt_mono_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints)
+runtime_profiler_class_failed (
+ MonoProfiler *prof,
+ MonoClass *klass)
{
- ep_char8_t runtime_module_path [256];
- const uint8_t object_guid [EP_GUID_SIZE] = { 0 };
- const uint16_t runtime_product_qfe_version = 0;
- const uint32_t startup_flags = 0;
- const uint8_t startup_mode = 0;
- const ep_char8_t *command_line = "";
+ ep_rt_mono_write_event_type_load_stop (m_class_get_byval_arg (klass));
+}
- if (!g_module_address ((void *)mono_init, runtime_module_path, sizeof (runtime_module_path), NULL, NULL, 0, NULL))
- runtime_module_path [0] = '\0';
+static
+void
+runtime_profiler_class_loaded (
+ MonoProfiler *prof,
+ MonoClass *klass)
+{
+ ep_rt_mono_write_event_type_load_stop (m_class_get_byval_arg (klass));
+}
- FireEtwRuntimeInformationDCStart (
- clr_instance_get_id (),
- RUNTIME_SKU_CORECLR,
- RuntimeProductMajorVersion,
- RuntimeProductMinorVersion,
- RuntimeProductPatchVersion,
- runtime_product_qfe_version,
- RuntimeFileMajorVersion,
- RuntimeFileMajorVersion,
- RuntimeFileBuildVersion,
- RuntimeFileRevisionVersion,
- startup_mode,
- startup_flags,
- command_line,
- object_guid,
- runtime_module_path,
- NULL,
- NULL);
+static
+void
+runtime_profiler_exception_throw (
+ MonoProfiler *prof,
+ MonoObject *exc)
+{
+ ep_rt_mono_write_event_exception_thrown (exc);
+}
- if (execution_checkpoints) {
- ep_rt_execution_checkpoint_array_iterator_t execution_checkpoints_iterator = ep_rt_execution_checkpoint_array_iterator_begin (execution_checkpoints);
- while (!ep_rt_execution_checkpoint_array_iterator_end (execution_checkpoints, &execution_checkpoints_iterator)) {
- EventPipeExecutionCheckpoint *checkpoint = ep_rt_execution_checkpoint_array_iterator_value (&execution_checkpoints_iterator);
- FireEtwExecutionCheckpointDCEnd (
- clr_instance_get_id (),
- checkpoint->name,
- checkpoint->timestamp,
- NULL,
- NULL);
- ep_rt_execution_checkpoint_array_iterator_next (&execution_checkpoints_iterator);
- }
- }
+static
+void
+runtime_profiler_exception_clause (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ uint32_t clause_num,
+ MonoExceptionEnum clause_type,
+ MonoObject *exc)
+{
+ ep_rt_mono_write_event_exception_clause (method, clause_num, clause_type, exc);
+}
- FireEtwDCEndInit_V1 (
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+runtime_profiler_monitor_contention (
+ MonoProfiler *prof,
+ MonoObject *obj)
+{
+ ep_rt_mono_write_event_monitor_contention_start (obj);
+}
- eventpipe_execute_rundown (
- fire_domain_rundown_events_func,
- fire_assembly_rundown_events_func,
- fire_method_rundown_events_func);
+static
+void
+runtime_profiler_monitor_acquired (
+ MonoProfiler *prof,
+ MonoObject *obj)
+{
+ ep_rt_mono_write_event_monitor_contention_stop (obj);
+}
- FireEtwDCEndComplete_V1 (
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+runtime_profiler_monitor_failed (
+ MonoProfiler *prof,
+ MonoObject *obj)
+{
+ ep_rt_mono_write_event_monitor_contention_stop (obj);
}
-bool
-ep_rt_mono_write_event_ee_startup_start (void)
+static
+void
+runtime_profiler_jit_code_buffer (
+ MonoProfiler *prof,
+ const mono_byte *buffer,
+ uint64_t size,
+ MonoProfilerCodeBufferType type,
+ const void *data)
{
- return FireEtwEEStartupStart_V1 (
- clr_instance_get_id (),
- NULL,
- NULL);
+ ep_rt_mono_write_event_method_jit_memory_allocated_for_code ((const uint8_t *)buffer, size, type, data);
}
-bool
-ep_rt_mono_write_event_jit_start (MonoMethod *method)
+void
+EventPipeEtwCallbackDotNETRuntime (
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data)
{
- if (!EventEnabledMethodJittingStarted_V1 ())
- return true;
+ ep_rt_config_requires_lock_not_held ();
- //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
- if (method) {
- uint64_t method_id = 0;
- uint64_t module_id = 0;
- uint32_t code_size = 0;
- uint32_t method_token = 0;
- char *method_namespace = NULL;
- const char *method_name = NULL;
- char *method_signature = NULL;
+ EP_ASSERT(is_enabled == 0 || is_enabled == 1) ;
+ EP_ASSERT (_ep_rt_dotnet_runtime_profiler_provider != NULL);
- //TODO: SendMethodDetailsEvent
+ match_any_keywords = (is_enabled == 1) ? match_any_keywords : 0;
- method_id = (uint64_t)method;
+ EP_LOCK_ENTER (section1)
+ uint64_t enabled_keywords = MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask;
- if (!method->dynamic)
- method_token = method->token;
+ if (profiler_callback_is_enabled(match_any_keywords, JIT_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, JIT_KEYWORD)) {
+ mono_profiler_set_jit_begin_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_jit_begin);
+ mono_profiler_set_jit_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_jit_failed);
+ mono_profiler_set_jit_done_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_jit_done);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, JIT_KEYWORD)) {
+ mono_profiler_set_jit_begin_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_jit_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_jit_done_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
+ }
- if (!mono_method_has_no_body (method)) {
- ERROR_DECL (error);
- MonoMethodHeader *header = mono_method_get_header_internal (method, error);
- if (header)
- code_size = header->code_size;
+ if (profiler_callback_is_enabled(match_any_keywords, LOADER_KEYWORD)) {
+ if (!profiler_callback_is_enabled(enabled_keywords, LOADER_KEYWORD)) {
+ mono_profiler_set_image_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_image_loaded);
+ mono_profiler_set_image_unloaded_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_image_unloaded);
+ mono_profiler_set_assembly_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_assembly_loaded);
+ mono_profiler_set_assembly_unloaded_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_assembly_unloaded);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, LOADER_KEYWORD)) {
+ mono_profiler_set_image_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_image_unloaded_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_assembly_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_assembly_unloaded_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
}
- method_name = method->name;
- method_signature = mono_signature_full_name (method->signature);
+ if (profiler_callback_is_enabled(match_any_keywords, APP_DOMAIN_RESOURCE_MANAGEMENT_KEYWORD | THREADING_KEYWORD)) {
+ if (!profiler_callback_is_enabled(enabled_keywords, APP_DOMAIN_RESOURCE_MANAGEMENT_KEYWORD | THREADING_KEYWORD)) {
+ mono_profiler_set_thread_started_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_thread_started);
+ mono_profiler_set_thread_stopped_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_thread_stopped);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, APP_DOMAIN_RESOURCE_MANAGEMENT_KEYWORD | THREADING_KEYWORD)) {
+ mono_profiler_set_thread_started_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_thread_stopped_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
+ }
- if (method->klass) {
- module_id = (uint64_t)m_class_get_image (method->klass);
- method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+ if (profiler_callback_is_enabled(match_any_keywords, TYPE_DIAGNOSTIC_KEYWORD)) {
+ if (!profiler_callback_is_enabled(enabled_keywords, TYPE_DIAGNOSTIC_KEYWORD)) {
+ mono_profiler_set_class_loading_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_class_loading);
+ mono_profiler_set_class_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_class_failed);
+ mono_profiler_set_class_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_class_loaded);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, TYPE_DIAGNOSTIC_KEYWORD)) {
+ mono_profiler_set_class_loading_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_class_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_class_loaded_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
}
- FireEtwMethodJittingStarted_V1 (
- method_id,
- module_id,
- method_token,
- code_size,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id (),
- NULL,
- NULL);
+ if (profiler_callback_is_enabled(match_any_keywords, EXCEPTION_KEYWORD)) {
+ if (!profiler_callback_is_enabled(enabled_keywords, EXCEPTION_KEYWORD)) {
+ mono_profiler_set_exception_throw_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_exception_throw);
+ mono_profiler_set_exception_clause_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_exception_clause);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, EXCEPTION_KEYWORD)) {
+ mono_profiler_set_exception_throw_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_exception_clause_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
+ }
- g_free (method_namespace);
- g_free (method_signature);
- }
+ if (profiler_callback_is_enabled(match_any_keywords, CONTENTION_KEYWORD)) {
+ if (!profiler_callback_is_enabled(enabled_keywords, CONTENTION_KEYWORD)) {
+ mono_profiler_set_monitor_contention_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_monitor_contention);
+ mono_profiler_set_monitor_acquired_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_monitor_acquired);
+ mono_profiler_set_monitor_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, runtime_profiler_monitor_failed);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, CONTENTION_KEYWORD)) {
+ mono_profiler_set_monitor_contention_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_monitor_acquired_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ mono_profiler_set_monitor_failed_callback (_ep_rt_dotnet_runtime_profiler_provider, NULL);
+ }
+ }
- return true;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level = level;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+ EP_LOCK_EXIT (section1)
+
+ep_on_exit:
+ ep_rt_config_requires_lock_not_held ();
+ return;
+
+ep_on_error:
+ ep_exit_error_handler ();
}
-bool
-ep_rt_mono_write_event_method_il_to_native_map (
- MonoMethod *method,
- MonoJitInfo *ji)
+void
+EventPipeEtwCallbackDotNETRuntimeRundown (
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data)
{
- if (!EventEnabledMethodILToNativeMap ())
- return true;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = level;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+}
- if (method) {
- // Under netcore we only have root domain.
- MonoDomain *root_domain = mono_get_root_domain ();
+void
+EventPipeEtwCallbackDotNETRuntimePrivate (
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data)
+{
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.Level = level;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+}
- uint64_t method_id = (uint64_t)method;
- uint32_t fixed_buffer [64];
- uint8_t *buffer = NULL;
+void
+EventPipeEtwCallbackDotNETRuntimeStress (
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data)
+{
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.Level = level;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
+ MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+}
- uint16_t offset_entries = 0;
- uint32_t *il_offsets = NULL;
- uint32_t *native_offsets = NULL;
+static
+void
+mono_profiler_app_domain_loading (
+ MonoProfiler *prof,
+ MonoDomain *domain)
+{
+ if (!EventEnabledMonoProfilerAppDomainLoading ())
+ return;
- MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, root_domain) : NULL;
- if (debug_info) {
- if (offset_entries != 0) {
- offset_entries = debug_info->num_line_numbers;
- size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
- if (needed_size > sizeof (fixed_buffer)) {
- buffer = g_new (uint8_t, needed_size);
- il_offsets = (uint32_t*)buffer;
- } else {
- il_offsets = fixed_buffer;
- }
- if (il_offsets) {
- native_offsets = il_offsets + offset_entries;
- for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
- il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
- native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
- }
- }
- }
+ uint64_t domain_id = (uint64_t)domain;
+ FireEtwMonoProfilerAppDomainLoading (
+ clr_instance_get_id (),
+ domain_id,
+ NULL,
+ NULL);
+}
- mono_debug_free_method_jit_info (debug_info);
- }
+static
+void
+mono_profiler_app_domain_loaded (
+ MonoProfiler *prof,
+ MonoDomain *domain)
+{
+ if (!EventEnabledMonoProfilerAppDomainLoaded ())
+ return;
- if (!il_offsets && !native_offsets) {
- // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
- EP_ASSERT (sizeof (fixed_buffer) >= sizeof (uint32_t) * 2);
- offset_entries = 1;
- il_offsets = fixed_buffer;
- native_offsets = il_offsets + offset_entries;
- il_offsets [0] = 0;
- native_offsets [0] = ji ? (uint32_t)ji->code_size : 0;
- }
+ uint64_t domain_id = (uint64_t)domain;
+ FireEtwMonoProfilerAppDomainLoaded (
+ clr_instance_get_id (),
+ domain_id,
+ NULL,
+ NULL);
+}
+
+static
+void
+mono_profiler_app_domain_unloading (
+ MonoProfiler *prof,
+ MonoDomain *domain)
+{
+ if (!EventEnabledMonoProfilerAppDomainUnloading ())
+ return;
+
+ uint64_t domain_id = (uint64_t)domain;
+ FireEtwMonoProfilerAppDomainUnloading (
+ clr_instance_get_id (),
+ domain_id,
+ NULL,
+ NULL);
+}
- FireEtwMethodILToNativeMap (
- method_id,
- 0,
- 0,
- offset_entries,
- il_offsets,
- native_offsets,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_app_domain_unloaded (
+ MonoProfiler *prof,
+ MonoDomain *domain)
+{
+ if (!EventEnabledMonoProfilerAppDomainUnloaded ())
+ return;
- g_free (buffer);
- }
+ uint64_t domain_id = (uint64_t)domain;
+ FireEtwMonoProfilerAppDomainUnloaded (
+ clr_instance_get_id (),
+ domain_id,
+ NULL,
+ NULL);
+}
- return true;
+static
+void
+mono_profiler_app_domain_name (
+ MonoProfiler *prof,
+ MonoDomain *domain,
+ const char *name)
+{
+ if (!EventEnabledMonoProfilerAppDomainName ())
+ return;
+
+ uint64_t domain_id = (uint64_t)domain;
+ FireEtwMonoProfilerAppDomainName (
+ clr_instance_get_id (),
+ domain_id,
+ (const ep_char8_t *)(name ? name : ""),
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_method_load (
+static
+inline
+void
+get_jit_data (
MonoMethod *method,
- MonoJitInfo *ji)
+ uint64_t *method_id,
+ uint64_t *module_id,
+ uint32_t *method_token)
{
- if (!EventEnabledMethodLoad_V1 () && !EventEnabledMethodLoadVerbose_V1())
- return true;
+ *method_id = (uint64_t)method;
+ *module_id = 0;
+ *method_token = 0;
- //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
if (method) {
- uint64_t method_id = 0;
- uint64_t module_id = 0;
- uint64_t method_code_start = ji ? (uint64_t)ji->code_start : 0;
- uint32_t method_code_size = ji ? (uint32_t)ji->code_size : 0;
- uint32_t method_token = 0;
- uint32_t method_flags = 0;
- uint8_t kind = MONO_CLASS_DEF;
- char *method_namespace = NULL;
- const char *method_name = NULL;
- char *method_signature = NULL;
- bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE);
-
- method_id = (uint64_t)method;
+ *method_token = method->token;
+ if (method->klass)
+ *module_id = (uint64_t)m_class_get_image (method->klass);
+ }
+}
- if (!method->dynamic)
- method_token = method->token;
+static
+void
+mono_profiler_jit_begin (
+ MonoProfiler *prof,
+ MonoMethod *method)
+{
+ if (!EventEnabledMonoProfilerJitBegin())
+ return;
- if (ji && mono_jit_info_get_generic_sharing_context (ji)) {
- method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
- verbose = true;
- }
+ uint64_t method_id;
+ uint64_t module_id;
+ uint32_t method_token;
- if (method->dynamic) {
- method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
- verbose = true;
- }
+ get_jit_data (method, &method_id, &module_id, &method_token);
- if (ji && !ji->from_aot && !ji->from_llvm) {
- method_flags |= METHOD_FLAGS_JITTED_METHOD;
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
- }
+ FireEtwMonoProfilerJitBegin (
+ clr_instance_get_id (),
+ method_id,
+ module_id,
+ method_token,
+ NULL,
+ NULL);
+}
- if (method->is_generic || method->is_inflated) {
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
- verbose = true;
- }
+static
+void
+mono_profiler_jit_failed (
+ MonoProfiler *prof,
+ MonoMethod *method)
+{
+ if (!EventEnabledMonoProfilerJitFailed())
+ return;
- if (method->klass) {
- module_id = (uint64_t)m_class_get_image (method->klass);
- kind = m_class_get_class_kind (method->klass);
- if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
- }
+ uint64_t method_id;
+ uint64_t module_id;
+ uint32_t method_token;
- //TODO: SendMethodDetailsEvent
+ get_jit_data (method, &method_id, &module_id, &method_token);
- if (verbose) {
- method_name = method->name;
- method_signature = mono_signature_full_name (method->signature);
+ FireEtwMonoProfilerJitFailed (
+ clr_instance_get_id (),
+ method_id,
+ module_id,
+ method_token,
+ NULL,
+ NULL);
+}
- if (method->klass)
- method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+static
+void
+mono_profiler_jit_done (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoJitInfo *ji)
+{
+ if (!EventEnabledMonoProfilerJitDone())
+ return;
- FireEtwMethodLoadVerbose_V1 (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id (),
- NULL,
- NULL);
+ uint64_t method_id;
+ uint64_t module_id;
+ uint32_t method_token;
- if (ji && (ji->from_aot || ji->from_llvm))
- FireEtwMethodLoadVerbose_V1 (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id (),
- NULL,
- NULL);
- } else {
- FireEtwMethodLoad_V1 (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION,
- clr_instance_get_id (),
- NULL,
- NULL);
+ get_jit_data (method, &method_id, &module_id, &method_token);
- if (ji && (ji->from_aot || ji->from_llvm))
- FireEtwMethodLoad_V1 (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION,
- clr_instance_get_id (),
- NULL,
- NULL);
- }
+ FireEtwMonoProfilerJitDone (
+ clr_instance_get_id (),
+ method_id,
+ module_id,
+ method_token,
+ NULL,
+ NULL);
+}
- g_free (method_namespace);
- g_free (method_signature);
- }
+static
+void
+mono_profiler_jit_chunk_created (
+ MonoProfiler *prof,
+ const mono_byte *chunk,
+ uintptr_t size)
+{
+ if (!EventEnabledMonoProfilerJitChunkCreated())
+ return;
- return true;
+ FireEtwMonoProfilerJitChunkCreated (
+ clr_instance_get_id (),
+ chunk,
+ (uint64_t)size,
+ NULL,
+ NULL);
}
static
-bool
-get_module_event_data (
- MonoImage *image,
- ModuleEventData *module_data)
+void
+mono_profiler_jit_chunk_destroyed (
+ MonoProfiler *prof,
+ const mono_byte *chunk)
{
- if (image && module_data) {
- memset (module_data->signature, 0, EP_GUID_SIZE);
+ if (!EventEnabledMonoProfilerJitChunkDestroyed())
+ return;
- // Under netcore we only have root domain.
- MonoDomain *root_domain = mono_get_root_domain ();
+ FireEtwMonoProfilerJitChunkDestroyed (
+ clr_instance_get_id (),
+ chunk,
+ NULL,
+ NULL);
+}
- module_data->domain_id = (uint64_t)root_domain;
- module_data->module_id = (uint64_t)image;
- module_data->assembly_id = (uint64_t)image->assembly;
+static
+void
+mono_profiler_jit_code_buffer (
+ MonoProfiler *prof,
+ const mono_byte *buffer,
+ uint64_t size,
+ MonoProfilerCodeBufferType type,
+ const void *data)
+{
+ if (!EventEnabledMonoProfilerJitCodeBuffer())
+ return;
- // TODO: Extract all module IL/Native paths and pdb metadata when available.
- module_data->module_il_path = "";
- module_data->module_il_pdb_path = "";
- module_data->module_native_path = "";
- module_data->module_native_pdb_path = "";
+ FireEtwMonoProfilerJitCodeBuffer (
+ clr_instance_get_id (),
+ buffer,
+ size,
+ (uint8_t)type,
+ NULL,
+ NULL);
+}
- module_data->module_il_pdb_age = 0;
- module_data->module_native_pdb_age = 0;
+static
+inline
+void
+get_class_data (
+ MonoClass *klass,
+ uint64_t *class_id,
+ uint64_t *module_id,
+ ep_char8_t **class_name)
+{
+ *class_id = (uint64_t)klass;
+ *module_id = 0;
- module_data->reserved_flags = 0;
+ if (klass)
+ *module_id = (uint64_t)m_class_get_image (klass);
- // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
- module_data->module_flags = MODULE_FLAGS_MANIFEST_MODULE;
- if (image->dynamic)
- module_data->module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
- if (image->aot_module)
- module_data->module_flags |= MODULE_FLAGS_NATIVE_MODULE;
+ if (klass && class_name)
+ *class_name = (ep_char8_t *)mono_type_get_name_full (m_class_get_byval_arg (klass), MONO_TYPE_NAME_FORMAT_IL);
+ else if (class_name)
+ *class_name = NULL;
+}
- module_data->module_il_path = image->filename ? image->filename : "";
- }
+static
+void
+mono_profiler_class_loading (
+ MonoProfiler *prof,
+ MonoClass *klass)
+{
+ if (!EventEnabledMonoProfilerClassLoading())
+ return;
- return true;
+ uint64_t class_id;
+ uint64_t module_id;
+
+ get_class_data (klass, &class_id, &module_id, NULL);
+
+ FireEtwMonoProfilerClassLoading (
+ clr_instance_get_id (),
+ class_id,
+ module_id,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_module_load (MonoImage *image)
+static
+void
+mono_profiler_class_failed (
+ MonoProfiler *prof,
+ MonoClass *klass)
{
- if (!EventEnabledModuleLoad_V2 () && !EventEnabledDomainModuleLoad_V1())
- return true;
+ if (!EventEnabledMonoProfilerClassFailed())
+ return;
- if (image) {
- ModuleEventData module_data;
- if (get_module_event_data (image, &module_data)) {
- FireEtwModuleLoad_V2 (
- module_data.module_id,
- module_data.assembly_id,
- module_data.module_flags,
- module_data.reserved_flags,
- module_data.module_il_path,
- module_data.module_native_path,
- clr_instance_get_id (),
- module_data.signature,
- module_data.module_il_pdb_age,
- module_data.module_il_pdb_path,
- module_data.signature,
- module_data.module_native_pdb_age,
- module_data.module_native_pdb_path,
- NULL,
- NULL);
+ uint64_t class_id;
+ uint64_t module_id;
- FireEtwDomainModuleLoad_V1 (
- module_data.module_id,
- module_data.assembly_id,
- module_data.domain_id,
- module_data.module_flags,
- module_data.reserved_flags,
- module_data.module_il_path,
- module_data.module_native_path,
- clr_instance_get_id (),
- NULL,
- NULL);
- }
- }
+ get_class_data (klass, &class_id, &module_id, NULL);
- return true;
+ FireEtwMonoProfilerClassFailed (
+ clr_instance_get_id (),
+ class_id,
+ module_id,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_module_unload (MonoImage *image)
+static
+void
+mono_profiler_class_loaded (
+ MonoProfiler *prof,
+ MonoClass *klass)
{
- if (!EventEnabledModuleUnload_V2())
- return true;
+ if (!EventEnabledMonoProfilerClassLoaded())
+ return;
- if (image) {
- ModuleEventData module_data;
- if (get_module_event_data (image, &module_data)) {
- FireEtwModuleUnload_V2 (
- module_data.module_id,
- module_data.assembly_id,
- module_data.module_flags,
- module_data.reserved_flags,
- module_data.module_il_path,
- module_data.module_native_path,
- clr_instance_get_id (),
- module_data.signature,
- module_data.module_il_pdb_age,
- module_data.module_il_pdb_path,
- module_data.signature,
- module_data.module_native_pdb_age,
- module_data.module_native_pdb_path,
- NULL,
- NULL);
- }
- }
+ uint64_t class_id;
+ uint64_t module_id;
+ ep_char8_t *class_name;
- return true;
+ get_class_data (klass, &class_id, &module_id, &class_name);
+
+ FireEtwMonoProfilerClassLoaded (
+ clr_instance_get_id (),
+ class_id,
+ module_id,
+ class_name ? class_name : "",
+ NULL,
+ NULL);
+
+ g_free (class_name);
}
static
-bool
-get_assembly_event_data (
- MonoAssembly *assembly,
- AssemblyEventData *assembly_data)
+inline
+void
+get_vtable_data (
+ MonoVTable *vtable,
+ uint64_t *vtable_id,
+ uint64_t *class_id,
+ uint64_t *domain_id)
{
- if (assembly && assembly_data) {
- // Under netcore we only have root domain.
- MonoDomain *root_domain = mono_get_root_domain ();
+ *vtable_id = (uint64_t)vtable;
+ *class_id = 0;
+ *domain_id = 0;
- assembly_data->domain_id = (uint64_t)root_domain;
- assembly_data->assembly_id = (uint64_t)assembly;
- assembly_data->binding_id = 0;
+ if (vtable) {
+ *class_id = (uint64_t)mono_vtable_class_internal (vtable);
+ *domain_id = (uint64_t)mono_vtable_domain_internal (vtable);
+ }
+}
- assembly_data->assembly_flags = 0;
- if (assembly->dynamic)
- assembly_data->assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
+static
+void
+mono_profiler_vtable_loading (
+ MonoProfiler *prof,
+ MonoVTable *vtable)
+{
+ if (!EventEnabledMonoProfilerVTableLoading())
+ return;
- if (assembly->image && assembly->image->aot_module)
- assembly_data->assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
+ uint64_t vtable_id;
+ uint64_t class_id;
+ uint64_t domain_id;
- assembly_data->assembly_name = mono_stringify_assembly_name (&assembly->aname);
- }
+ get_vtable_data (vtable, &vtable_id, &class_id, &domain_id);
- return true;
+ FireEtwMonoProfilerVTableLoading (
+ clr_instance_get_id (),
+ vtable_id,
+ class_id,
+ domain_id,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly)
+static
+void
+mono_profiler_vtable_failed (
+ MonoProfiler *prof,
+ MonoVTable *vtable)
{
- if (!EventEnabledAssemblyLoad_V1 ())
- return true;
-
- if (assembly) {
- AssemblyEventData assembly_data;
- if (get_assembly_event_data (assembly, &assembly_data)) {
- FireEtwAssemblyLoad_V1 (
- assembly_data.assembly_id,
- assembly_data.domain_id,
- assembly_data.binding_id,
- assembly_data.assembly_flags,
- assembly_data.assembly_name,
- clr_instance_get_id (),
- NULL,
- NULL);
+ if (!EventEnabledMonoProfilerVTableFailed())
+ return;
- g_free (assembly_data.assembly_name);
- }
- }
+ uint64_t vtable_id;
+ uint64_t class_id;
+ uint64_t domain_id;
- return true;
+ get_vtable_data (vtable, &vtable_id, &class_id, &domain_id);
+
+ FireEtwMonoProfilerVTableFailed (
+ clr_instance_get_id (),
+ vtable_id,
+ class_id,
+ domain_id,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_assembly_unload (MonoAssembly *assembly)
+static
+void
+mono_profiler_vtable_loaded (
+ MonoProfiler *prof,
+ MonoVTable *vtable)
{
- if (!EventEnabledAssemblyUnload_V1 ())
- return true;
-
- if (assembly) {
- AssemblyEventData assembly_data;
- if (get_assembly_event_data (assembly, &assembly_data)) {
- FireEtwAssemblyUnload_V1 (
- assembly_data.assembly_id,
- assembly_data.domain_id,
- assembly_data.binding_id,
- assembly_data.assembly_flags,
- assembly_data.assembly_name,
- clr_instance_get_id (),
- NULL,
- NULL);
+ if (!EventEnabledMonoProfilerVTableLoaded())
+ return;
- g_free (assembly_data.assembly_name);
- }
- }
+ uint64_t vtable_id;
+ uint64_t class_id;
+ uint64_t domain_id;
- return true;
+ get_vtable_data (vtable, &vtable_id, &class_id, &domain_id);
+
+ FireEtwMonoProfilerVTableLoaded (
+ clr_instance_get_id (),
+ vtable_id,
+ class_id,
+ domain_id,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_thread_created (ep_rt_thread_id_t tid)
+static
+void
+mono_profiler_module_loading (
+ MonoProfiler *prof,
+ MonoImage *image)
{
- if (!EventEnabledThreadCreated ())
- return true;
-
- uint64_t managed_thread = 0;
- uint64_t native_thread_id = ep_rt_thread_id_t_to_uint64_t (tid);
- uint64_t managed_thread_id = 0;
- uint32_t flags = 0;
+ if (!EventEnabledMonoProfilerModuleLoading ())
+ return;
+
+ FireEtwMonoProfilerModuleLoading (
+ clr_instance_get_id (),
+ (uint64_t)image,
+ NULL,
+ NULL);
+}
- MonoThread *thread = mono_thread_current ();
- if (thread && mono_thread_info_get_tid (thread->thread_info) == tid) {
- managed_thread_id = (uint64_t)mono_thread_get_managed_id (thread);
- managed_thread = (uint64_t)thread;
+static
+void
+mono_profiler_module_failed (
+ MonoProfiler *prof,
+ MonoImage *image)
+{
+ if (!EventEnabledMonoProfilerModuleFailed ())
+ return;
- switch (mono_thread_info_get_flags (thread->thread_info)) {
- case MONO_THREAD_INFO_FLAGS_NO_GC:
- case MONO_THREAD_INFO_FLAGS_NO_SAMPLE:
- flags |= THREAD_FLAGS_GC_SPECIAL;
- }
+ FireEtwMonoProfilerModuleFailed (
+ clr_instance_get_id (),
+ (uint64_t)image,
+ NULL,
+ NULL);
+}
- if (mono_gc_is_finalizer_thread (thread))
- flags |= THREAD_FLAGS_FINALIZER;
+static
+void
+mono_profiler_module_loaded (
+ MonoProfiler *prof,
+ MonoImage *image)
+{
+ if (!EventEnabledMonoProfilerModuleLoaded ())
+ return;
+
+ uint64_t module_id = (uint64_t)image;
+ const ep_char8_t *module_path = NULL;
+ const ep_char8_t *module_guid = NULL;
- if (thread->threadpool_thread)
- flags |= THREAD_FLAGS_THREADPOOL_WORKER;
+ if (image) {
+ ModuleEventData module_data;
+ if (get_module_event_data (image, &module_data))
+ module_path = (const ep_char8_t *)module_data.module_il_path;
+ module_guid = (const ep_char8_t *)mono_image_get_guid (image);
}
- FireEtwThreadCreated (
- managed_thread,
- (uint64_t)mono_get_root_domain (),
- flags,
- managed_thread_id,
- native_thread_id,
+ FireEtwMonoProfilerModuleLoaded (
clr_instance_get_id (),
+ module_id,
+ module_path ? module_path : "",
+ module_guid ? module_guid : "",
NULL,
NULL);
+}
- return true;
+static
+void
+mono_profiler_module_unloading (
+ MonoProfiler *prof,
+ MonoImage *image)
+{
+ if (!EventEnabledMonoProfilerModuleUnloading ())
+ return;
+
+ FireEtwMonoProfilerModuleUnloading (
+ clr_instance_get_id (),
+ (uint64_t)image,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_thread_terminated (ep_rt_thread_id_t tid)
+static
+void
+mono_profiler_module_unloaded (
+ MonoProfiler *prof,
+ MonoImage *image)
{
- if (!EventEnabledThreadTerminated ())
- return true;
+ if (!EventEnabledMonoProfilerModuleUnloaded ())
+ return;
+
+ uint64_t module_id = (uint64_t)image;
+ const ep_char8_t *module_path = NULL;
+ const ep_char8_t *module_guid = NULL;
- uint64_t managed_thread = 0;
- MonoThread *thread = mono_thread_current ();
- if (thread && mono_thread_info_get_tid (thread->thread_info) == tid)
- managed_thread = (uint64_t)thread;
+ if (image) {
+ ModuleEventData module_data;
+ if (get_module_event_data (image, &module_data))
+ module_path = (const ep_char8_t *)module_data.module_il_path;
+ module_guid = (const ep_char8_t *)mono_image_get_guid (image);
+ }
- FireEtwThreadTerminated (
- managed_thread,
- (uint64_t)mono_get_root_domain (),
+ FireEtwMonoProfilerModuleUnloaded (
clr_instance_get_id (),
+ module_id,
+ module_path ? module_path : "",
+ module_guid ? module_guid : "",
NULL,
NULL);
-
- return true;
}
static
-uint32_t
-get_type_start_id (MonoType *type)
+inline
+void
+get_assembly_data (
+ MonoAssembly *assembly,
+ uint64_t *assembly_id,
+ uint64_t *module_id,
+ ep_char8_t **assembly_name)
{
- uint32_t start_id = (uint32_t)(uintptr_t)type;
+ *assembly_id = (uint64_t)assembly;
+ *module_id = 0;
- start_id = (((start_id * 215497) >> 16) ^ ((start_id * 1823231) + start_id));
-
- // Mix in highest bits on 64-bit systems only
- if (sizeof (type) > 4)
- start_id = start_id ^ (((uint64_t)type >> 31) >> 1);
+ if (assembly)
+ *module_id = (uint64_t)mono_assembly_get_image_internal (assembly);
- return start_id;
+ if (assembly && assembly_name)
+ *assembly_name = (ep_char8_t *)mono_stringify_assembly_name (&assembly->aname);
+ else if (assembly_name)
+ *assembly_name = NULL;
}
-bool
-ep_rt_mono_write_event_type_load_start (MonoType *type)
+static
+void
+mono_profiler_assembly_loading (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
{
- if (!EventEnabledTypeLoadStart ())
- return true;
+ if (!EventEnabledMonoProfilerAssemblyLoading ())
+ return;
+
+ uint64_t assembly_id;
+ uint64_t module_id;
- FireEtwTypeLoadStart (
- get_type_start_id (type),
+ get_assembly_data (assembly, &assembly_id, &module_id, NULL);
+
+ FireEtwMonoProfilerAssemblyLoading (
clr_instance_get_id (),
+ assembly_id,
+ module_id,
NULL,
NULL);
-
- return true;
}
-bool
-ep_rt_mono_write_event_type_load_stop (MonoType *type)
+static
+void
+mono_profiler_assembly_loaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
{
- if (!EventEnabledTypeLoadStop ())
- return true;
+ if (!EventEnabledMonoProfilerAssemblyLoaded ())
+ return;
- char *type_name = NULL;
- if (type)
- type_name = mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
+ uint64_t assembly_id;
+ uint64_t module_id;
+ ep_char8_t *assembly_name;
- FireEtwTypeLoadStop (
- get_type_start_id (type),
+ get_assembly_data (assembly, &assembly_id, &module_id, &assembly_name);
+
+ FireEtwMonoProfilerAssemblyLoaded (
clr_instance_get_id (),
- 6 /* CLASS_LOADED */,
- (uint64_t)type,
- type_name,
+ assembly_id,
+ module_id,
+ assembly_name ? assembly_name : "",
NULL,
NULL);
- g_free (type_name);
-
- return true;
+ g_free (assembly_name);
}
static
-gboolean
-get_exception_ip_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- void *data)
-{
- *(uintptr_t *)data = (uintptr_t)MONO_CONTEXT_GET_IP (ctx);
- return TRUE;
-}
-
-bool
-ep_rt_mono_write_event_exception_thrown (MonoObject *obj)
+void
+mono_profiler_assembly_unloading (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
{
- if (!EventEnabledExceptionThrown_V1 ())
- return true;
-
- if (obj) {
- ERROR_DECL (error);
- char *type_name = NULL;
- char *exception_message = NULL;
- uint16_t flags = 0;
- uint32_t hresult = 0;
- uintptr_t ip = 0;
-
- if (mono_object_isinst_checked ((MonoObject *) obj, mono_get_exception_class (), error)) {
- MonoException *exception = (MonoException *)obj;
- flags |= EXCEPTION_THROWN_FLAGS_IS_CLS_COMPLIANT;
- if (exception->inner_ex)
- flags |= EXCEPTION_THROWN_FLAGS_HAS_INNER;
- exception_message = ep_rt_utf16_to_utf8_string (mono_string_chars_internal (exception->message), mono_string_length_internal (exception->message));
- hresult = exception->hresult;
- }
+ if (!EventEnabledMonoProfilerAssemblyUnloading ())
+ return;
+
+ uint64_t assembly_id;
+ uint64_t module_id;
- if (mono_get_eh_callbacks ()->mono_walk_stack_with_ctx)
- mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (get_exception_ip_func, NULL, MONO_UNWIND_SIGNAL_SAFE, (void *)&ip);
+ get_assembly_data (assembly, &assembly_id, &module_id, NULL);
- type_name = mono_type_get_name_full (m_class_get_byval_arg (mono_object_class (obj)), MONO_TYPE_NAME_FORMAT_IL);
+ FireEtwMonoProfilerAssemblyUnloading (
+ clr_instance_get_id (),
+ assembly_id,
+ module_id,
+ NULL,
+ NULL);
+}
- FireEtwExceptionThrown_V1 (
- type_name,
- exception_message,
- (void *)&ip,
- hresult,
- flags,
- clr_instance_get_id (),
- NULL,
- NULL);
+static
+void
+mono_profiler_assembly_unloaded (
+ MonoProfiler *prof,
+ MonoAssembly *assembly)
+{
+ if (!EventEnabledMonoProfilerAssemblyUnloaded ())
+ return;
- if (!mono_component_profiler_clauses_enabled ()) {
- FireEtwExceptionThrownStop (
- NULL,
- NULL);
- }
+ uint64_t assembly_id;
+ uint64_t module_id;
+ ep_char8_t *assembly_name;
- g_free (exception_message);
- g_free (type_name);
+ get_assembly_data (assembly, &assembly_id, &module_id, &assembly_name);
- mono_error_cleanup (error);
- }
+ FireEtwMonoProfilerAssemblyUnloaded (
+ clr_instance_get_id (),
+ assembly_id,
+ module_id,
+ assembly_name ? assembly_name : "",
+ NULL,
+ NULL);
- return true;
+ g_free (assembly_name);
}
-bool
-ep_rt_mono_write_event_exception_clause (
+static
+void
+mono_profiler_method_enter (
+ MonoProfiler *prof,
MonoMethod *method,
- uint32_t clause_num,
- MonoExceptionEnum clause_type,
- MonoObject *obj)
+ MonoProfilerCallContext *context)
{
- if (!mono_component_profiler_clauses_enabled ())
- return true;
-
- if ((clause_type == MONO_EXCEPTION_CLAUSE_FAULT || clause_type == MONO_EXCEPTION_CLAUSE_NONE) && (!EventEnabledExceptionCatchStart() || !EventEnabledExceptionCatchStop()))
- return true;
-
- if (clause_type == MONO_EXCEPTION_CLAUSE_FILTER && (!EventEnabledExceptionFilterStart() || !EventEnabledExceptionFilterStop()))
- return true;
-
- if (clause_type == MONO_EXCEPTION_CLAUSE_FINALLY && (!EventEnabledExceptionFinallyStart() || !EventEnabledExceptionFinallyStop()))
- return true;
-
- uintptr_t ip = 0; //TODO: Have profiler pass along IP of handler block.
- uint64_t method_id = (uint64_t)method;
- char *method_name = NULL;
-
- method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
-
- if ((clause_type == MONO_EXCEPTION_CLAUSE_FAULT || clause_type == MONO_EXCEPTION_CLAUSE_NONE)) {
- FireEtwExceptionCatchStart (
- (uint64_t)ip,
- method_id,
- (const ep_char8_t *)method_name,
- clr_instance_get_id (),
- NULL,
- NULL);
-
- FireEtwExceptionCatchStop (
- NULL,
- NULL);
-
- FireEtwExceptionThrownStop (
- NULL,
- NULL);
- }
+ if (!EventEnabledMonoProfilerMethodEnter ())
+ return;
- if (clause_type == MONO_EXCEPTION_CLAUSE_FILTER) {
- FireEtwExceptionFilterStart (
- (uint64_t)ip,
- method_id,
- (const ep_char8_t *)method_name,
- clr_instance_get_id (),
- NULL,
- NULL);
+ FireEtwMonoProfilerMethodEnter (
+ clr_instance_get_id (),
+ (uint64_t)method,
+ NULL,
+ NULL);
+}
- FireEtwExceptionFilterStop (
- NULL,
- NULL);
- }
+static
+void
+mono_profiler_method_leave (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoProfilerCallContext *context)
+{
+ if (!EventEnabledMonoProfilerMethodLeave ())
+ return;
- if (clause_type == MONO_EXCEPTION_CLAUSE_FINALLY) {
- FireEtwExceptionFinallyStart (
- (uint64_t)ip,
- method_id,
- (const ep_char8_t *)method_name,
- clr_instance_get_id (),
- NULL,
- NULL);
+ FireEtwMonoProfilerMethodLeave (
+ clr_instance_get_id (),
+ (uint64_t)method,
+ NULL,
+ NULL);
+}
- FireEtwExceptionFinallyStop (
- NULL,
- NULL);
- }
+static
+void
+mono_profiler_method_tail_call (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoMethod *target_method)
+{
+ if (!EventEnabledMonoProfilerMethodTailCall ())
+ return;
- g_free (method_name);
- return true;
+ FireEtwMonoProfilerMethodTailCall (
+ clr_instance_get_id (),
+ (uint64_t)method,
+ NULL,
+ NULL);
}
-bool
-ep_rt_mono_write_event_monitor_contention_start (MonoObject *obj)
+static
+void
+mono_profiler_method_exception_leave (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ MonoObject *exc)
{
- if (!EventEnabledContentionStart_V1 ())
- return true;
+ if (!EventEnabledMonoProfilerMethodExceptionLeave ())
+ return;
- FireEtwContentionStart_V1 (
- 0 /* ManagedContention */,
+ FireEtwMonoProfilerMethodExceptionLeave (
clr_instance_get_id (),
+ (uint64_t)method,
NULL,
NULL);
-
- return true;
}
-bool
-ep_rt_mono_write_event_monitor_contention_stop (MonoObject *obj)
+static
+void
+mono_profiler_method_free (
+ MonoProfiler *prof,
+ MonoMethod *method)
{
- if (!EventEnabledContentionStop ())
- return true;
+ if (!EventEnabledMonoProfilerMethodFree ())
+ return;
- FireEtwContentionStop (
- 0 /* ManagedContention */,
+ FireEtwMonoProfilerMethodFree (
clr_instance_get_id (),
+ (uint64_t)method,
NULL,
NULL);
-
- return true;
}
-bool
-ep_rt_mono_write_event_method_jit_memory_allocated_for_code (
- const uint8_t *buffer,
- uint64_t size,
- MonoProfilerCodeBufferType type,
- const void *data)
+static
+void
+mono_profiler_method_begin_invoke (
+ MonoProfiler *prof,
+ MonoMethod *method)
{
- if (!EventEnabledMethodJitMemoryAllocatedForCode ())
- return true;
-
- if (type != MONO_PROFILER_CODE_BUFFER_METHOD)
- return true;
-
- uint64_t method_id = 0;
- uint64_t module_id = 0;
-
- if (data) {
- MonoMethod *method;
- method = (MonoMethod *)data;
- method_id = (uint64_t)method;
- if (method->klass)
- module_id = (uint64_t)(uint64_t)m_class_get_image (method->klass);
- }
+ if (!EventEnabledMonoProfilerMethodBeginInvoke ())
+ return;
- FireEtwMethodJitMemoryAllocatedForCode (
- method_id,
- module_id,
- size,
- 0,
- size,
- 0 /* CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN */,
+ FireEtwMonoProfilerMethodBeginInvoke (
clr_instance_get_id (),
+ (uint64_t)method,
NULL,
NULL);
-
- return true;
}
-bool
-ep_rt_write_event_threadpool_worker_thread_start (
- uint32_t active_thread_count,
- uint32_t retired_worker_thread_count,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_method_end_invoke (
+ MonoProfiler *prof,
+ MonoMethod *method)
{
- return FireEtwThreadPoolWorkerThreadStart (
- active_thread_count,
- retired_worker_thread_count,
- clr_instance_id,
- NULL,
- NULL) == 0 ? true : false;
-}
+ if (!EventEnabledMonoProfilerMethodEndInvoke ())
+ return;
-bool
-ep_rt_write_event_threadpool_worker_thread_stop (
- uint32_t active_thread_count,
- uint32_t retired_worker_thread_count,
- uint16_t clr_instance_id)
-{
- return FireEtwThreadPoolWorkerThreadStop (
- active_thread_count,
- retired_worker_thread_count,
- clr_instance_id,
+ FireEtwMonoProfilerMethodEndInvoke (
+ clr_instance_get_id (),
+ (uint64_t)method,
NULL,
- NULL) == 0 ? true : false;
+ NULL);
}
-bool
-ep_rt_write_event_threadpool_worker_thread_wait (
- uint32_t active_thread_count,
- uint32_t retired_worker_thread_count,
- uint16_t clr_instance_id)
+static
+MonoProfilerCallInstrumentationFlags
+mono_profiler_method_instrumentation (
+ MonoProfiler *prof,
+ MonoMethod *method)
{
- return FireEtwThreadPoolWorkerThreadWait (
- active_thread_count,
- retired_worker_thread_count,
- clr_instance_id,
- NULL,
- NULL) == 0 ? true : false;
-}
+ if (_ep_rt_dotnet_mono_profiler_provider_callspec.len > 0 && !mono_callspec_eval (method, &_ep_rt_dotnet_mono_profiler_provider_callspec))
+ return MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
-bool
-ep_rt_write_event_threadpool_worker_thread_adjustment_sample (
- double throughput,
- uint16_t clr_instance_id)
-{
- return FireEtwThreadPoolWorkerThreadAdjustmentSample (
- throughput,
- clr_instance_id,
- NULL,
- NULL) == 0 ? true : false;
+ return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
+ MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
+ MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
+ MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
}
-bool
-ep_rt_write_event_threadpool_worker_thread_adjustment_adjustment (
- double average_throughput,
- uint32_t networker_thread_count,
- /*NativeRuntimeEventSource.ThreadAdjustmentReasonMap*/ int32_t reason,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_exception_throw (
+ MonoProfiler *prof,
+ MonoObject *exc)
{
- return FireEtwThreadPoolWorkerThreadAdjustmentAdjustment (
- average_throughput,
- networker_thread_count,
- reason,
- clr_instance_id,
+ if (!EventEnabledMonoProfilerExceptionThrow ())
+ return;
+
+ uint64_t type_id = 0;
+
+ if (exc && mono_object_class(exc))
+ type_id = (uint64_t)m_class_get_byval_arg (mono_object_class(exc));
+
+ FireEtwMonoProfilerExceptionThrow (
+ clr_instance_get_id (),
+ type_id,
+ SGEN_POINTER_UNTAG_ALL (exc),
NULL,
- NULL) == 0 ? true : false;
+ NULL);
}
-bool
-ep_rt_write_event_threadpool_worker_thread_adjustment_stats (
- double duration,
- double throughput,
- double threadpool_worker_thread_wait,
- double throughput_wave,
- double throughput_error_estimate,
- double average_throughput_error_estimate,
- double throughput_ratio,
- double confidence,
- double new_control_setting,
- uint16_t new_thread_wave_magnitude,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_exception_clause (
+ MonoProfiler *prof,
+ MonoMethod *method,
+ uint32_t clause_num,
+ MonoExceptionEnum clause_type,
+ MonoObject *exc)
{
- return FireEtwThreadPoolWorkerThreadAdjustmentStats (
- duration,
- throughput,
- threadpool_worker_thread_wait,
- throughput_wave,
- throughput_error_estimate,
- average_throughput_error_estimate,
- throughput_ratio,
- confidence,
- new_control_setting,
- new_thread_wave_magnitude,
- clr_instance_id,
+ if (!EventEnabledMonoProfilerExceptionClause ())
+ return;
+
+ uint64_t type_id = 0;
+
+ if (exc && mono_object_class(exc))
+ type_id = (uint64_t)m_class_get_byval_arg (mono_object_class(exc));
+
+ FireEtwMonoProfilerExceptionClause (
+ clr_instance_get_id (),
+ (uint8_t)clause_type,
+ clause_num,
+ (uint64_t)method,
+ type_id,
+ SGEN_POINTER_UNTAG_ALL (exc),
NULL,
- NULL) == 0 ? true : false;
+ NULL);
}
-bool
-ep_rt_write_event_threadpool_io_enqueue (
- intptr_t native_overlapped,
- intptr_t overlapped,
- bool multi_dequeues,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_gc_event (
+ MonoProfiler *prof,
+ MonoProfilerGCEvent gc_event,
+ uint32_t generation,
+ mono_bool serial)
{
- return FireEtwThreadPoolIOEnqueue (
- (const void *)native_overlapped,
- (const void *)overlapped,
- multi_dequeues,
- clr_instance_id,
+ if (!EventEnabledMonoProfilerGCEvent ())
+ return;
+
+ // TODO: Needs to be async safe.
+ /*FireEtwMonoProfilerGCEvent (
+ clr_instance_get_id (),
+ (uint8_t)gc_event,
+ generation,
NULL,
- NULL) == 0 ? true : false;
+ NULL);*/
}
-bool
-ep_rt_write_event_threadpool_io_dequeue (
- intptr_t native_overlapped,
- intptr_t overlapped,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_gc_allocation (
+ MonoProfiler *prof,
+ MonoObject *object)
{
- return FireEtwThreadPoolIODequeue (
- (const void *)native_overlapped,
- (const void *)overlapped,
- clr_instance_id,
+ if (!EventEnabledMonoProfilerGCAllocation ())
+ return;
+
+ uint64_t vtable_id = 0;
+ uint64_t object_size = 0;
+
+ if (object) {
+ vtable_id = (uint64_t)mono_object_get_vtable_internal (object);
+ object_size = (uint64_t)mono_object_get_size_internal (object);
+
+ /* account for object alignment */
+ object_size += 7;
+ object_size &= ~7;
+ }
+
+ FireEtwMonoProfilerGCAllocation (
+ clr_instance_get_id (),
+ vtable_id,
+ SGEN_POINTER_UNTAG_ALL (object),
+ object_size,
NULL,
- NULL) == 0 ? true : false;
+ NULL);
}
-bool
-ep_rt_write_event_threadpool_working_thread_count (
- uint16_t count,
- uint16_t clr_instance_id)
+static
+void
+mono_profiler_gc_moves (
+ MonoProfiler *prof,
+ MonoObject *const* objects,
+ uint64_t count)
{
- return FireEtwThreadPoolWorkingThreadCount (
- count,
- clr_instance_id,
- NULL,
- NULL) == 0 ? true : false;
+ if (!EventEnabledMonoProfilerGCMoves ())
+ return;
+
+ // TODO: Needs to be async safe.
+ /*uint64_t obj_count = count / 2;
+
+ GCObjectAddressData data [32];
+ uint64_t data_chunks = obj_count / G_N_ELEMENTS (data);
+ uint64_t data_rest = obj_count % G_N_ELEMENTS (data);
+ uint64_t current_obj = 0;
+
+ for (int chunk = 0; chunk < data_chunks; chunk++) {
+ for (int i = 0; i < G_N_ELEMENTS (data); i++) {
+ data [i].object = SGEN_POINTER_UNTAG_ALL (objects [current_obj++]);
+ data [i].address = objects [current_obj++];
+ }
+
+ FireEtwMonoProfilerGCMoves (
+ clr_instance_get_id (),
+ G_N_ELEMENTS (data),
+ sizeof (GCObjectAddressData),
+ data,
+ NULL,
+ NULL);
+ }
+
+ if ((data_rest != 0)&& (data_rest % 2 == 0)) {
+ for (int i = 0; i < data_rest; i++) {
+ data [i].object = SGEN_POINTER_UNTAG_ALL (objects [current_obj++]);
+ data [i].address = objects [current_obj++];
+ }
+
+ FireEtwMonoProfilerGCMoves (
+ clr_instance_get_id (),
+ data_rest,
+ sizeof (GCObjectAddressData),
+ data,
+ NULL,
+ NULL);
+ }*/
}
static
void
-profiler_jit_begin (
+mono_profiler_gc_resize (
MonoProfiler *prof,
- MonoMethod *method)
+ uintptr_t size)
{
- ep_rt_mono_write_event_jit_start (method);
+ if (!EventEnabledMonoProfilerGCResize ())
+ return;
+
+ // TODO: Needs to be async safe.
+ /*FireEtwMonoProfilerGCResize (
+ clr_instance_get_id (),
+ (uint64_t)size,
+ NULL,
+ NULL);*/
}
static
void
-profiler_jit_failed (
+mono_profiler_gc_handle_created (
MonoProfiler *prof,
- MonoMethod *method)
+ uint32_t handle,
+ MonoGCHandleType type,
+ MonoObject *object)
{
- //TODO: CoreCLR doesn't have this case, so no failure event currently exists.
+ if (!EventEnabledMonoProfilerGCHandleCreated ())
+ return;
+
+ FireEtwMonoProfilerGCHandleCreated (
+ clr_instance_get_id (),
+ handle,
+ (uint8_t)type,
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_jit_done (
+mono_profiler_gc_handle_deleted (
MonoProfiler *prof,
- MonoMethod *method,
- MonoJitInfo *ji)
+ uint32_t handle,
+ MonoGCHandleType type)
{
- ep_rt_mono_write_event_method_load (method, ji);
- ep_rt_mono_write_event_method_il_to_native_map (method, ji);
+ if (!EventEnabledMonoProfilerGCHandleDeleted ())
+ return;
+
+ FireEtwMonoProfilerGCHandleDeleted (
+ clr_instance_get_id (),
+ handle,
+ (uint8_t)type,
+ NULL,
+ NULL);
}
static
void
-profiler_image_loaded (
- MonoProfiler *prof,
- MonoImage *image)
+mono_profiler_gc_finalizing (MonoProfiler *prof)
{
- if (image && image->heap_pdb.size == 0)
- ep_rt_mono_write_event_module_load (image);
+ if (!EventEnabledMonoProfilerGCFinalizing ())
+ return;
+
+ FireEtwMonoProfilerGCFinalizing (
+ clr_instance_get_id (),
+ NULL,
+ NULL);
}
static
void
-profiler_image_unloaded (
- MonoProfiler *prof,
- MonoImage *image)
+mono_profiler_gc_finalized (MonoProfiler *prof)
{
- if (image && image->heap_pdb.size == 0)
- ep_rt_mono_write_event_module_unload (image);
+ if (!EventEnabledMonoProfilerGCFinalized ())
+ return;
+
+ FireEtwMonoProfilerGCFinalized (
+ clr_instance_get_id (),
+ NULL,
+ NULL);
}
static
void
-profiler_assembly_loaded (
+mono_profiler_gc_finalizing_object (
MonoProfiler *prof,
- MonoAssembly *assembly)
+ MonoObject *object)
{
- ep_rt_mono_write_event_assembly_load (assembly);
+ if (!EventEnabledMonoProfilerGCFinalizingObject ())
+ return;
+
+ FireEtwMonoProfilerGCFinalizingObject (
+ clr_instance_get_id (),
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_assembly_unloaded (
+mono_profiler_gc_finalized_object (
MonoProfiler *prof,
- MonoAssembly *assembly)
+ MonoObject * object)
{
- ep_rt_mono_write_event_assembly_unload (assembly);
+ if (!EventEnabledMonoProfilerGCFinalizedObject ())
+ return;
+
+ FireEtwMonoProfilerGCFinalizedObject (
+ clr_instance_get_id (),
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_thread_started (
+mono_profiler_gc_root_register (
MonoProfiler *prof,
- uintptr_t tid)
+ const mono_byte *start,
+ uintptr_t size,
+ MonoGCRootSource source,
+ const void * key,
+ const char * name)
{
- ep_rt_mono_write_event_thread_created (ep_rt_uint64_t_to_thread_id_t (tid));
+ if (!EventEnabledMonoProfilerGCRootRegister ())
+ return;
+
+ FireEtwMonoProfilerGCRootRegister (
+ clr_instance_get_id (),
+ start,
+ (uint64_t)size,
+ (uint8_t) source,
+ (uint64_t)key,
+ (const ep_char8_t *)(name ? name : ""),
+ NULL,
+ NULL);
}
static
void
-profiler_thread_stopped (
+mono_profiler_gc_root_unregister (
MonoProfiler *prof,
- uintptr_t tid)
+ const mono_byte *start)
{
- ep_rt_mono_write_event_thread_terminated (ep_rt_uint64_t_to_thread_id_t (tid));
+ if (!EventEnabledMonoProfilerGCRootUnregister ())
+ return;
+
+ FireEtwMonoProfilerGCRootUnregister (
+ clr_instance_get_id (),
+ start,
+ NULL,
+ NULL);
}
static
void
-profiler_class_loading (
+mono_profiler_gc_roots (
MonoProfiler *prof,
- MonoClass *klass)
+ uint64_t count,
+ const mono_byte *const * addresses,
+ MonoObject *const * objects)
{
- ep_rt_mono_write_event_type_load_start (m_class_get_byval_arg (klass));
+ if (!EventEnabledMonoProfilerGCRoots ())
+ return;
+
+ // TODO: Needs to be async safe.
+ /*GCAddressObjectData data [32];
+ uint64_t data_chunks = count / G_N_ELEMENTS (data);
+ uint64_t data_rest = count % G_N_ELEMENTS (data);
+ uint64_t current_obj = 0;
+
+ for (int chunk = 0; chunk < data_chunks; chunk++) {
+ for (int i = 0; i < G_N_ELEMENTS (data); i++) {
+ data [i].address = addresses [current_obj];
+ data [i].object = SGEN_POINTER_UNTAG_ALL (objects [current_obj]);
+ current_obj++;
+ }
+
+ FireEtwMonoProfilerGCRoots (
+ clr_instance_get_id (),
+ G_N_ELEMENTS (data),
+ sizeof (GCAddressObjectData),
+ data,
+ NULL,
+ NULL);
+ }
+
+ if (data_rest != 0) {
+ for (int i = 0; i < data_rest; i++) {
+ data [i].address = addresses [current_obj];
+ data [i].object = SGEN_POINTER_UNTAG_ALL (objects [current_obj]);
+ current_obj++;
+ }
+
+ FireEtwMonoProfilerGCRoots (
+ clr_instance_get_id (),
+ data_rest,
+ sizeof (GCAddressObjectData),
+ data,
+ NULL,
+ NULL);
+ }*/
}
static
void
-profiler_class_failed (
+mono_profiler_monitor_contention (
MonoProfiler *prof,
- MonoClass *klass)
+ MonoObject *object)
{
- ep_rt_mono_write_event_type_load_stop (m_class_get_byval_arg (klass));
+ if (!EventEnabledMonoProfilerMonitorContention ())
+ return;
+
+ FireEtwMonoProfilerMonitorContention (
+ clr_instance_get_id (),
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_class_loaded (
+mono_profiler_monitor_failed (
MonoProfiler *prof,
- MonoClass *klass)
+ MonoObject *object)
{
- ep_rt_mono_write_event_type_load_stop (m_class_get_byval_arg (klass));
+ if (!EventEnabledMonoProfilerMonitorFailed ())
+ return;
+
+ FireEtwMonoProfilerMonitorFailed (
+ clr_instance_get_id (),
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_exception_throw (
+mono_profiler_monitor_acquired (
MonoProfiler *prof,
- MonoObject *exc)
+ MonoObject *object)
{
- ep_rt_mono_write_event_exception_thrown (exc);
+ if (!EventEnabledMonoProfilerMonitorAcquired ())
+ return;
+
+ FireEtwMonoProfilerMonitorAcquired (
+ clr_instance_get_id (),
+ SGEN_POINTER_UNTAG_ALL (object),
+ NULL,
+ NULL);
}
static
void
-profiler_exception_clause (
+mono_profiler_thread_started (
MonoProfiler *prof,
- MonoMethod *method,
- uint32_t clause_num,
- MonoExceptionEnum clause_type,
- MonoObject *exc)
+ uintptr_t tid)
{
- ep_rt_mono_write_event_exception_clause (method, clause_num, clause_type, exc);
+ if (!EventEnabledMonoProfilerThreadStarted ())
+ return;
+
+ FireEtwMonoProfilerThreadStarted (
+ clr_instance_get_id (),
+ (uint64_t)tid,
+ NULL,
+ NULL);
}
static
void
-profiler_monitor_contention (
+mono_profiler_thread_stopping (
MonoProfiler *prof,
- MonoObject *obj)
+ uintptr_t tid)
{
- ep_rt_mono_write_event_monitor_contention_start (obj);
+ if (!EventEnabledMonoProfilerThreadStopping ())
+ return;
+
+ FireEtwMonoProfilerThreadStopping (
+ clr_instance_get_id (),
+ (uint64_t)tid,
+ NULL,
+ NULL);
}
static
void
-profiler_monitor_acquired (
+mono_profiler_thread_stopped (
MonoProfiler *prof,
- MonoObject *obj)
+ uintptr_t tid)
{
- ep_rt_mono_write_event_monitor_contention_stop (obj);
+ if (!EventEnabledMonoProfilerThreadStopped ())
+ return;
+
+ FireEtwMonoProfilerThreadStopped (
+ clr_instance_get_id (),
+ (uint64_t)tid,
+ NULL,
+ NULL);
}
static
void
-profiler_monitor_failed (
+mono_profiler_thread_exited (
MonoProfiler *prof,
- MonoObject *obj)
+ uintptr_t tid)
{
- ep_rt_mono_write_event_monitor_contention_stop (obj);
+ if (!EventEnabledMonoProfilerThreadExited ())
+ return;
+
+ FireEtwMonoProfilerThreadExited (
+ clr_instance_get_id (),
+ (uint64_t)tid,
+ NULL,
+ NULL);
}
static
void
-profiler_jit_code_buffer (
+mono_profiler_thread_name (
MonoProfiler *prof,
- const mono_byte *buffer,
- uint64_t size,
- MonoProfilerCodeBufferType type,
- const void *data)
+ uintptr_t tid,
+ const char *name)
{
- ep_rt_mono_write_event_method_jit_memory_allocated_for_code ((const uint8_t *)buffer, size, type, data);
+ if (!EventEnabledMonoProfilerThreadName ())
+ return;
+
+ FireEtwMonoProfilerThreadName (
+ clr_instance_get_id (),
+ (uint64_t)tid,
+ (ep_char8_t *)(name ? name : ""),
+ NULL,
+ NULL);
}
void
-EventPipeEtwCallbackDotNETRuntime (
+EventPipeEtwCallbackDotNETRuntimeMonoProfiler (
const uint8_t *source_id,
unsigned long is_enabled,
uint8_t level,
@@ -2992,55 +4907,261 @@ EventPipeEtwCallbackDotNETRuntime (
ep_rt_config_requires_lock_not_held ();
EP_ASSERT(is_enabled == 0 || is_enabled == 1) ;
- EP_ASSERT (_ep_rt_mono_profiler != NULL);
+ EP_ASSERT (_ep_rt_dotnet_mono_profiler_provider != NULL);
+
+ match_any_keywords = (is_enabled == 1) ? match_any_keywords : 0;
EP_LOCK_ENTER (section1)
- if (is_enabled == 1 && !MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) {
- // Add profiler callbacks for DotNETRuntime provider events.
- mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, profiler_jit_begin);
- mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, profiler_jit_failed);
- mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, profiler_jit_done);
- mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, profiler_image_loaded);
- mono_profiler_set_image_unloaded_callback (_ep_rt_mono_profiler, profiler_image_unloaded);
- mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, profiler_assembly_loaded);
- mono_profiler_set_assembly_unloaded_callback (_ep_rt_mono_profiler, profiler_assembly_unloaded);
- mono_profiler_set_thread_started_callback (_ep_rt_mono_profiler, profiler_thread_started);
- mono_profiler_set_thread_stopped_callback (_ep_rt_mono_profiler, profiler_thread_stopped);
- mono_profiler_set_class_loading_callback (_ep_rt_mono_profiler, profiler_class_loading);
- mono_profiler_set_class_failed_callback (_ep_rt_mono_profiler, profiler_class_failed);
- mono_profiler_set_class_loaded_callback (_ep_rt_mono_profiler, profiler_class_loaded);
- mono_profiler_set_exception_throw_callback (_ep_rt_mono_profiler, profiler_exception_throw);
- mono_profiler_set_exception_clause_callback (_ep_rt_mono_profiler, profiler_exception_clause);
- mono_profiler_set_monitor_contention_callback (_ep_rt_mono_profiler, profiler_monitor_contention);
- mono_profiler_set_monitor_acquired_callback (_ep_rt_mono_profiler, profiler_monitor_acquired);
- mono_profiler_set_monitor_failed_callback (_ep_rt_mono_profiler, profiler_monitor_failed);
- mono_profiler_set_jit_code_buffer_callback (_ep_rt_mono_profiler, profiler_jit_code_buffer);
- } else if (is_enabled == 0 && MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) {
- // Remove profiler callbacks for DotNETRuntime provider events.
- mono_profiler_set_jit_code_buffer_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_monitor_failed_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_monitor_acquired_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_monitor_contention_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_exception_clause_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_exception_throw_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_class_loaded_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_class_failed_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_class_loading_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_thread_started_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_thread_started_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_assembly_unloaded_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_image_unloaded_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, NULL);
- mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, NULL);
+ uint64_t enabled_keywords = MICROSOFT_DOTNETRUNTIME_MONO_PROFILER_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask;
+
+ if (profiler_callback_is_enabled(match_any_keywords, LOADER_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, LOADER_KEYWORD)) {
+ mono_profiler_set_domain_loading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_app_domain_loading);
+ mono_profiler_set_domain_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_app_domain_loaded);
+ mono_profiler_set_domain_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_app_domain_unloading);
+ mono_profiler_set_domain_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_app_domain_unloaded);
+ mono_profiler_set_domain_name_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_app_domain_name);
+ mono_profiler_set_image_loading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_module_loading);
+ mono_profiler_set_image_failed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_module_failed);
+ mono_profiler_set_image_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_module_loaded);
+ mono_profiler_set_image_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_module_unloading);
+ mono_profiler_set_image_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_module_unloaded);
+ mono_profiler_set_assembly_loading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_assembly_loading);
+ mono_profiler_set_assembly_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_assembly_loaded);
+ mono_profiler_set_assembly_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_assembly_unloading);
+ mono_profiler_set_assembly_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_assembly_unloaded);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, LOADER_KEYWORD)) {
+ mono_profiler_set_domain_loading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_domain_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_domain_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_domain_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_domain_name_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_image_loading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_image_failed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_image_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_image_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_image_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_assembly_loading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_assembly_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_assembly_unloading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_assembly_unloaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, JIT_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, JIT_KEYWORD)) {
+ mono_profiler_set_jit_begin_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_begin);
+ mono_profiler_set_jit_failed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_failed);
+ mono_profiler_set_jit_done_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_done);
+ mono_profiler_set_jit_chunk_created_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_chunk_created);
+ mono_profiler_set_jit_chunk_destroyed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_chunk_destroyed);
+ mono_profiler_set_jit_code_buffer_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_jit_code_buffer);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, JIT_KEYWORD)) {
+ mono_profiler_set_jit_begin_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_jit_failed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_jit_done_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_jit_chunk_created_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_jit_chunk_destroyed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_jit_code_buffer_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, TYPE_LOADING_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, TYPE_LOADING_KEYWORD)) {
+ mono_profiler_set_class_loading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_class_loading);
+ mono_profiler_set_class_failed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_class_failed);
+ mono_profiler_set_class_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_class_loaded);
+ mono_profiler_set_vtable_loading_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_vtable_loading);
+ mono_profiler_set_vtable_failed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_vtable_failed);
+ mono_profiler_set_vtable_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_vtable_loaded);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, TYPE_LOADING_KEYWORD)) {
+ mono_profiler_set_class_loading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_class_failed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_class_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_vtable_loading_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_vtable_failed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_vtable_loaded_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, METHOD_TRACING_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, METHOD_TRACING_KEYWORD)) {
+ mono_profiler_set_method_enter_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_enter);
+ mono_profiler_set_method_leave_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_leave);
+ mono_profiler_set_method_tail_call_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_tail_call);
+ mono_profiler_set_method_exception_leave_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_exception_leave);
+ mono_profiler_set_method_free_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_free);
+ mono_profiler_set_method_begin_invoke_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_begin_invoke);
+ mono_profiler_set_method_end_invoke_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_end_invoke);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, METHOD_TRACING_KEYWORD)) {
+ mono_profiler_set_method_enter_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_leave_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_tail_call_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_exception_leave_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_free_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_begin_invoke_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_method_end_invoke_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, EXCEPTION_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, EXCEPTION_KEYWORD)) {
+ mono_profiler_set_exception_throw_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_exception_throw);
+ mono_profiler_set_exception_clause_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_exception_clause);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, EXCEPTION_KEYWORD)) {
+ mono_profiler_set_exception_throw_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_exception_clause_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD)) {
+ mono_profiler_set_gc_event_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_event);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD)) {
+ mono_profiler_set_gc_event_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_ALLOCATION_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_ALLOCATION_KEYWORD)) {
+ mono_profiler_set_gc_allocation_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_allocation);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_ALLOCATION_KEYWORD)) {
+ mono_profiler_set_gc_allocation_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_MOVES_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_MOVES_KEYWORD)) {
+ mono_profiler_set_gc_moves_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_moves);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_MOVES_KEYWORD)) {
+ mono_profiler_set_gc_moves_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_RESIZE_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_RESIZE_KEYWORD)) {
+ mono_profiler_set_gc_resize_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_resize);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_RESIZE_KEYWORD)) {
+ mono_profiler_set_gc_resize_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_HANDLE_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_HANDLE_KEYWORD)) {
+ mono_profiler_set_gc_handle_created_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_handle_created);
+ mono_profiler_set_gc_handle_deleted_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_handle_deleted);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_HANDLE_KEYWORD)) {
+ mono_profiler_set_gc_handle_created_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_handle_deleted_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_FINALIZATION_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_FINALIZATION_KEYWORD)) {
+ mono_profiler_set_gc_finalizing_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_finalizing);
+ mono_profiler_set_gc_finalized_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_finalized);
+ mono_profiler_set_gc_finalizing_object_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_finalizing_object);
+ mono_profiler_set_gc_finalized_object_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_finalized_object);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_FINALIZATION_KEYWORD)) {
+ mono_profiler_set_gc_finalizing_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_finalized_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_finalizing_object_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_finalized_object_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, GC_KEYWORD | GC_ROOT_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_ROOT_KEYWORD)) {
+ mono_profiler_set_gc_root_register_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_root_register);
+ mono_profiler_set_gc_root_unregister_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_root_unregister);
+ mono_profiler_set_gc_roots_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_gc_roots);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, GC_KEYWORD | GC_ROOT_KEYWORD)) {
+ mono_profiler_set_gc_root_register_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_root_unregister_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_gc_roots_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, MONITOR_KEYWORD | CONTENTION_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, MONITOR_KEYWORD | CONTENTION_KEYWORD)) {
+ mono_profiler_set_monitor_contention_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_monitor_contention);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, MONITOR_KEYWORD | CONTENTION_KEYWORD)) {
+ mono_profiler_set_monitor_contention_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, MONITOR_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, MONITOR_KEYWORD)) {
+ mono_profiler_set_monitor_failed_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_monitor_failed);
+ mono_profiler_set_monitor_acquired_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_monitor_acquired);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, MONITOR_KEYWORD)) {
+ mono_profiler_set_monitor_failed_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_monitor_acquired_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (profiler_callback_is_enabled(match_any_keywords, THREADING_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, THREADING_KEYWORD)) {
+ mono_profiler_set_thread_started_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_thread_started);
+ mono_profiler_set_thread_stopping_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_thread_stopping);
+ mono_profiler_set_thread_stopped_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_thread_stopped);
+ mono_profiler_set_thread_exited_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_thread_exited);
+ mono_profiler_set_thread_name_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_thread_name);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, THREADING_KEYWORD)) {
+ mono_profiler_set_thread_started_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_thread_stopping_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_thread_stopped_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_thread_exited_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ mono_profiler_set_thread_name_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
+
+ if (!_ep_rt_dotnet_mono_profiler_provider_callspec.enabled) {
+ if (profiler_callback_is_enabled(match_any_keywords, METHOD_INSTRUMENTATION_KEYWORD)) {
+ if (!profiler_callback_is_enabled (enabled_keywords, METHOD_INSTRUMENTATION_KEYWORD)) {
+ mono_profiler_set_call_instrumentation_filter_callback (_ep_rt_dotnet_mono_profiler_provider, mono_profiler_method_instrumentation);
+ }
+ } else {
+ if (profiler_callback_is_enabled (enabled_keywords, METHOD_INSTRUMENTATION_KEYWORD)) {
+ mono_profiler_set_call_instrumentation_filter_callback (_ep_rt_dotnet_mono_profiler_provider, NULL);
+ }
+ }
}
- EP_LOCK_EXIT (section1)
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level = level;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+ MICROSOFT_DOTNETRUNTIME_MONO_PROFILER_PROVIDER_EVENTPIPE_Context.Level = level;
+ MICROSOFT_DOTNETRUNTIME_MONO_PROFILER_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
+ MICROSOFT_DOTNETRUNTIME_MONO_PROFILER_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
+ EP_LOCK_EXIT (section1)
ep_on_exit:
ep_rt_config_requires_lock_not_held ();
@@ -3050,51 +5171,6 @@ EventPipeEtwCallbackDotNETRuntime (
ep_exit_error_handler ();
}
-void
-EventPipeEtwCallbackDotNETRuntimeRundown (
- const uint8_t *source_id,
- unsigned long is_enabled,
- uint8_t level,
- uint64_t match_any_keywords,
- uint64_t match_all_keywords,
- EventFilterDescriptor *filter_data,
- void *callback_data)
-{
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = level;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
-}
-
-void
-EventPipeEtwCallbackDotNETRuntimePrivate (
- const uint8_t *source_id,
- unsigned long is_enabled,
- uint8_t level,
- uint64_t match_any_keywords,
- uint64_t match_all_keywords,
- EventFilterDescriptor *filter_data,
- void *callback_data)
-{
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.Level = level;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
-}
-
-void
-EventPipeEtwCallbackDotNETRuntimeStress (
- const uint8_t *source_id,
- unsigned long is_enabled,
- uint8_t level,
- uint64_t match_any_keywords,
- uint64_t match_all_keywords,
- EventFilterDescriptor *filter_data,
- void *callback_data)
-{
- MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.Level = level;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords;
- MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false);
-}
-
#endif /* ENABLE_PERFTRACING */
MONO_EMPTY_SOURCE_FILE(eventpipe_rt_mono);
diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h
index 2c3a5f7e36d707..49b6456cdb9df8 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono.h
+++ b/src/mono/mono/eventpipe/ep-rt-mono.h
@@ -2344,6 +2344,16 @@ EventPipeEtwCallbackDotNETRuntimeStress (
EventFilterDescriptor *filter_data,
void *callback_data);
+void
+EventPipeEtwCallbackDotNETRuntimeMonoProfiler (
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data);
+
#endif /* ENABLE_PERFTRACING */
#endif /* __EVENTPIPE_RT_MONO_H__ */
diff --git a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst
index f74d476889e65d..ad52dd9f8c8ebb 100644
--- a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst
+++ b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst
@@ -45,3 +45,4 @@ ThreadPoolWorkingThreadCount
ThreadTerminated
TypeLoadStart
TypeLoadStop
+Microsoft-DotNETRuntimeMonoProfiler:*
\ No newline at end of file