diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props index 7871e7d61a77da..bb0135898ad02c 100644 --- a/src/coreclr/clr.featuredefines.props +++ b/src/coreclr/clr.featuredefines.props @@ -22,8 +22,6 @@ false false - - false false diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 0b37a72192cc33..b21c66f05adcba 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -79,9 +79,14 @@ add_definitions(-DFEATURE_DEFAULT_INTERFACES) if(FEATURE_EVENT_TRACE) add_compile_definitions(FEATURE_EVENT_TRACE) add_definitions(-DFEATURE_PERFTRACING) -else(FEATURE_EVENT_TRACE) +elseif(FEATURE_PERFTRACING) + add_definitions(-DFEATURE_PERFTRACING) + if(CLR_CROSS_COMPONENTS_BUILD) + add_custom_target(eventing_headers) + endif() +else() add_custom_target(eventing_headers) # add a dummy target to avoid checking for FEATURE_EVENT_TRACE in multiple places -endif(FEATURE_EVENT_TRACE) +endif() if(FEATURE_GDBJIT) add_definitions(-DFEATURE_GDBJIT) endif() diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake index 0cf973e1e8013c..d8f20db1d4c770 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -23,13 +23,19 @@ if(CLR_CMAKE_TARGET_TIZEN_LINUX) set(FEATURE_GDBJIT_LANGID_CS 1) endif() +# FEATURE_EVENT_TRACE: Enables the full eventing infrastructure (generated FireEtw* functions, +# EventPipe write calls, ETW on Windows). Set on all platforms except cross-component WASM builds. if(NOT DEFINED FEATURE_EVENT_TRACE) - if (NOT CLR_CMAKE_TARGET_BROWSER AND NOT (CLR_CROSS_COMPONENTS_BUILD AND CLR_CMAKE_TARGET_ARCH_WASM)) + if (NOT (CLR_CROSS_COMPONENTS_BUILD AND CLR_CMAKE_TARGET_ARCH_WASM)) # To actually disable FEATURE_EVENT_TRACE, also change clr.featuredefines.props set(FEATURE_EVENT_TRACE 1) endif() endif(NOT DEFINED FEATURE_EVENT_TRACE) +# FEATURE_EVENTSOURCE_XPLAT: Enables the LTTng-based XplatEventLogger path (LTTNG_TRACE_CONTEXT, +# XplatEventLogger, XplatEventLoggerController, and the generated FireEtXplat* functions). +# Currently Linux-only (excluding Android). Used as the sole guard for all LTTng-related code; +# platforms without this flag (Windows, macOS, Browser, WASI) use EventPipe-only eventing. if(NOT DEFINED FEATURE_EVENTSOURCE_XPLAT) if (CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID AND NOT (CLR_CROSS_COMPONENTS_BUILD AND CLR_CMAKE_TARGET_ARCH_WASM)) # To actually disable FEATURE_EVENTSOURCE_XPLAT, also change clr.featuredefines.props @@ -37,9 +43,14 @@ if(NOT DEFINED FEATURE_EVENTSOURCE_XPLAT) endif() endif(NOT DEFINED FEATURE_EVENTSOURCE_XPLAT) -if(NOT DEFINED FEATURE_PERFTRACING AND FEATURE_EVENT_TRACE) - set(FEATURE_PERFTRACING 1) -endif(NOT DEFINED FEATURE_PERFTRACING AND FEATURE_EVENT_TRACE) +# FEATURE_PERFTRACING: Enables the EventPipe diagnostics subsystem (event sessions, IPC protocol, +# diagnostic server). Set whenever FEATURE_EVENT_TRACE is set, or when threadless perftracing is +# explicitly requested via FEATURE_PERFTRACING_DISABLE_THREADS. +if(NOT DEFINED FEATURE_PERFTRACING) + if(FEATURE_EVENT_TRACE OR FEATURE_PERFTRACING_DISABLE_THREADS) + set(FEATURE_PERFTRACING 1) + endif() +endif(NOT DEFINED FEATURE_PERFTRACING) if(NOT DEFINED FEATURE_DBGIPC) if(CLR_CMAKE_TARGET_UNIX) diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index b81b8386bcc0dc..16cb14bf278228 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -121,6 +121,7 @@ enum EtwGCSettingFlags #define ETWFireEvent(EventName) FireEtw##EventName(GetClrInstanceId()) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) +#if defined(FEATURE_EVENTSOURCE_XPLAT) #define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword) || \ (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword))) #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ @@ -128,6 +129,12 @@ enum EtwGCSettingFlags #define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) +#else // FEATURE_EVENTSOURCE_XPLAT +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword)) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword)) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword)) +#endif // FEATURE_EVENTSOURCE_XPLAT #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) #else //defined(FEATURE_PERFTRACING) #define ETW_INLINE @@ -248,16 +255,11 @@ struct ProfilingScanContext; extern UINT32 g_nClrInstanceId; #define GetClrInstanceId() (static_cast(g_nClrInstanceId)) -#if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#if defined(HOST_UNIX) && defined(FEATURE_EVENT_TRACE) #define KEYWORDZERO 0x0 - -#define DEF_LTTNG_KEYWORD_ENABLED 1 -#ifdef FEATURE_EVENT_TRACE #include "clrproviders.h" -#endif // FEATURE_EVENT_TRACE #include "clrconfig.h" - -#endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#endif // defined(HOST_UNIX) && defined(FEATURE_EVENT_TRACE) #if defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) @@ -416,7 +418,7 @@ class XplatEventLoggerConfiguration }; #endif // defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) -#if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#if defined(FEATURE_EVENTSOURCE_XPLAT) class XplatEventLoggerController { @@ -436,7 +438,7 @@ class XplatEventLoggerController { ActivateAllKeywordsOfAllProviders(); } -#ifdef FEATURE_EVENT_TRACE +#if defined(FEATURE_EVENT_TRACE) && defined(HOST_UNIX) else { LTTNG_TRACE_CONTEXT *provider = GetProvider(providerName); @@ -453,7 +455,7 @@ class XplatEventLoggerController static void ActivateAllKeywordsOfAllProviders() { -#ifdef FEATURE_EVENT_TRACE +#if defined(FEATURE_EVENT_TRACE) && defined(HOST_UNIX) for (LTTNG_TRACE_CONTEXT * const provider : ALL_LTTNG_PROVIDERS_CONTEXT) { provider->EnabledKeywordsBitmask = (ULONGLONG)(-1); @@ -464,7 +466,7 @@ class XplatEventLoggerController } private: -#ifdef FEATURE_EVENT_TRACE +#if defined(FEATURE_EVENT_TRACE) && defined(HOST_UNIX) static LTTNG_TRACE_CONTEXT * const GetProvider(LPCWSTR providerName) { auto length = u16_strlen(providerName); @@ -490,7 +492,7 @@ class XplatEventLogger return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); } -#ifdef FEATURE_EVENT_TRACE +#if defined(FEATURE_EVENT_TRACE) && defined(HOST_UNIX) inline static bool IsProviderEnabled(DOTNET_TRACE_CONTEXT providerCtx) { return providerCtx.LttngProvider->IsEnabled; @@ -557,7 +559,7 @@ class XplatEventLogger }; -#endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#endif // defined(FEATURE_EVENTSOURCE_XPLAT) #if defined(FEATURE_EVENT_TRACE) diff --git a/src/coreclr/interpreter/CMakeLists.txt b/src/coreclr/interpreter/CMakeLists.txt index fb6dd25cc4c9c6..f4f88b9ed3260b 100644 --- a/src/coreclr/interpreter/CMakeLists.txt +++ b/src/coreclr/interpreter/CMakeLists.txt @@ -47,6 +47,10 @@ add_library_clr(clrinterpreter_objects OBJECT ${INTERPRETER_SOURCES}) target_include_directories(clrinterpreter_objects PRIVATE ../jitshared) +if (FEATURE_PERFTRACING_DISABLE_THREADS) + target_compile_definitions(clrinterpreter_objects PRIVATE PERFTRACING_DISABLE_THREADS) +endif() + if (NOT CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(clrinterpreter_objects PROPERTIES EXCLUDE_FROM_ALL $) endif() diff --git a/src/coreclr/scripts/genEventPipe.py b/src/coreclr/scripts/genEventPipe.py index 762fcffe94bdb4..6f801099df02e3 100644 --- a/src/coreclr/scripts/genEventPipe.py +++ b/src/coreclr/scripts/genEventPipe.py @@ -181,12 +181,20 @@ def generateClrEventPipeWriteEventsImpl( "void Init" + providerPrettyName + "(void)\n{\n") + if runtimeFlavor.coreclr: + callbackExpr = ("\n#ifdef FEATURE_EVENT_TRACE\n" + + " " + eventPipeCallbackCastExpr + "(" + callbackName + ")\n" + + "#else\n" + + " nullptr\n" + + "#endif\n ") + else: + callbackExpr = eventPipeCallbackCastExpr + "(" + callbackName + ")" WriteEventImpl.append( " EventPipeProvider" + providerPrettyName + " = " + createProviderFunc + "(" + providerPrettyName + - "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\n") + "Name, " + callbackExpr + ");\n") for eventNode in eventNodes: eventName = eventNode.getAttribute('symbol') templateName = eventNode.getAttribute('template') diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index 9aaa0df0e085b1..6d4006a4c49a28 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -439,12 +439,15 @@ def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is if runtimeFlavor.coreclr or write_xplatheader or runtimeFlavor.nativeaot: if not is_host_windows: - # native AOT does not support non-windows eventing other than via event pipe + # native AOT and browser/wasi do not support non-windows eventing other than via event pipe if not runtimeFlavor.nativeaot: - clrallEvents.append(" || (XplatEventLogger" + + clrallEvents.append("\n#if defined(FEATURE_EVENTSOURCE_XPLAT)\n") + clrallEvents.append(" || (XplatEventLogger" + ("::" if target_cpp else "_") + "IsEventLoggingEnabled() && EventXplatEnabled" + - eventName + "());}\n\n") + eventName + "())\n") + clrallEvents.append("#endif // FEATURE_EVENTSOURCE_XPLAT\n") + clrallEvents.append(";}\n\n") else: clrallEvents.append(";}\n\n") else: @@ -534,8 +537,12 @@ def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is fnbody.append("ActivityId,RelatedActivityId);\n") if runtimeFlavor.coreclr or write_xplatheader: + if not is_host_windows: + fnbody.append("#if defined(FEATURE_EVENTSOURCE_XPLAT)\n") fnbody.append(lindent) fnbody.append("status &= FireEtXplat" + eventName + "(" + ''.join(line) + ");\n") + if not is_host_windows: + fnbody.append("#endif // FEATURE_EVENTSOURCE_XPLAT\n") if runtimeFlavor.nativeaot: if providerName == "Microsoft-Windows-DotNETRuntime" or providerName == "Microsoft-Windows-DotNETRuntimePrivate" or providerName == "Microsoft-Windows-DotNETRuntimeRundown": @@ -868,7 +875,9 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; +#if defined(FEATURE_EVENTSOURCE_XPLAT) PLTTNG_TRACE_CONTEXT LttngProvider; +#endif } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #endif // DOTNET_TRACE_CONTEXT_DEF """ @@ -894,7 +903,9 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern """) if not is_host_windows and not runtimeFlavor.nativeaot: Clrproviders.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT + Clrproviders.write("#if defined(FEATURE_EVENTSOURCE_XPLAT)\n") Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT + Clrproviders.write("#endif // FEATURE_EVENTSOURCE_XPLAT\n") Clrproviders.write(dotnet_trace_context_typedef_unix + "\n") allProviders = [] @@ -910,7 +921,9 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" Clrproviders.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') lttngProviderCtxName = providerSymbol + "_LTTNG_Context" + Clrproviders.write('#if defined(FEATURE_EVENTSOURCE_XPLAT)\n') Clrproviders.write('__attribute__((weak)) LTTNG_TRACE_CONTEXT ' + lttngProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + Clrproviders.write('#endif // FEATURE_EVENTSOURCE_XPLAT\n') Clrproviders.write("// Keywords\n"); for keywordNode in providerNode.getElementsByTagName('keyword'): @@ -934,10 +947,12 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern # define and initialize runtime providers' DOTNET_TRACE_CONTEXT depending on the platform if not is_host_windows and not runtimeFlavor.nativeaot: + Clrproviders.write('#if defined(FEATURE_EVENTSOURCE_XPLAT)\n') Clrproviders.write('#define NB_PROVIDERS ' + str(nbProviders) + '\n') Clrproviders.write(('constexpr ' if target_cpp else 'static const ') + 'LTTNG_TRACE_CONTEXT * ALL_LTTNG_PROVIDERS_CONTEXT[NB_PROVIDERS] = { ') Clrproviders.write(', '.join(allProviders)) Clrproviders.write(' };\n') + Clrproviders.write('#endif // FEATURE_EVENTSOURCE_XPLAT\n') clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h") diff --git a/src/coreclr/vm/eventing/CMakeLists.txt b/src/coreclr/vm/eventing/CMakeLists.txt index 39fb58c2f46daf..f5faa23294c328 100644 --- a/src/coreclr/vm/eventing/CMakeLists.txt +++ b/src/coreclr/vm/eventing/CMakeLists.txt @@ -40,10 +40,13 @@ add_custom_command( set_source_files_properties(${EventingHeaders} PROPERTIES GENERATED TRUE) add_custom_target(eventing_headers DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp) -add_dependencies(eventing_headers eventprovider) - -add_subdirectory(eventpipe) if(CLR_CMAKE_HOST_WIN32) add_subdirectory(EtwProvider) endif() + +if (TARGET eventprovider) + add_dependencies(eventing_headers eventprovider) +endif() + +add_subdirectory(eventpipe) diff --git a/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt b/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt index e6a4ba24e3bead..5822b478b2d63e 100644 --- a/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt +++ b/src/coreclr/vm/eventing/eventpipe/CMakeLists.txt @@ -44,6 +44,7 @@ add_library_clr(eventpipe_gen_objs OBJECT ${GEN_EVENTPIPE_SOURCES}) target_precompile_headers(eventpipe_gen_objs PRIVATE [["common.h"]]) set_target_properties(eventpipe_gen_objs PROPERTIES LINKER_LANGUAGE CXX) add_dependencies(eventpipe_gen_objs eventing_headers) +target_compile_definitions(eventpipe_gen_objs PRIVATE FEATURE_PERFTRACING) add_library_clr(eventpipe_objs OBJECT ${CORECLR_EVENTPIPE_SHIM_SOURCES} ${CORECLR_EVENTPIPE_SHIM_HEADERS}) set_target_properties(eventpipe_objs PROPERTIES @@ -53,6 +54,10 @@ set_target_properties(eventpipe_objs PROPERTIES ) add_dependencies(eventpipe_objs eventing_headers) target_link_libraries(eventpipe_objs PRIVATE dn-diagnosticserver dn-eventpipe) +target_compile_definitions(eventpipe_objs PRIVATE FEATURE_PERFTRACING) +if (FEATURE_PERFTRACING_DISABLE_THREADS) + target_compile_definitions(eventpipe_objs PRIVATE PERFTRACING_DISABLE_THREADS) +endif() # The CoreCLR EventPipe runtime is C++, but the EventPipe and DiagnosticServer sources are C. # Forcibly override them to build as C++. diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index ebb46b8eb5396c..bc331427218e0b 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -434,11 +434,13 @@ ep_rt_provider_config_init (EventPipeProviderConfiguration *provider_config) { STATIC_CONTRACT_NOTHROW; +#ifdef FEATURE_EVENT_TRACE 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_DOTNET_Context.EventPipeProvider.Level = (UCHAR) ep_provider_config_get_logging_level (provider_config); MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.EnabledKeywordsBitmask = ep_provider_config_get_keywords (provider_config); MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled = true; } +#endif } // This function is auto-generated from /src/scripts/genEventPipe.py @@ -469,9 +471,13 @@ ep_rt_providers_validate_all_disabled (void) { STATIC_CONTRACT_NOTHROW; +#ifdef FEATURE_EVENT_TRACE return (!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled && !MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled && !MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context.EventPipeProvider.IsEnabled); +#else + return true; +#endif } static @@ -667,6 +673,8 @@ ep_rt_byte_array_free (uint8_t *ptr) * Event. */ +#ifndef PERFTRACING_DISABLE_THREADS + static void ep_rt_wait_event_alloc ( @@ -765,6 +773,79 @@ ep_rt_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) return wait_event->event->IsValid (); } +#else // PERFTRACING_DISABLE_THREADS + +// In single-threaded mode, wait events are no-ops. INVALID_HANDLE_VALUE is used as +// the "allocated" sentinel (distinguishing allocated from freed/NULL). + +static +inline +void +ep_rt_wait_event_alloc ( + ep_rt_wait_event_handle_t *wait_event, + bool manual, + bool initial) +{ + STATIC_CONTRACT_NOTHROW; + EP_ASSERT (wait_event != NULL); + wait_event->event = (CLREventStatic *)INVALID_HANDLE_VALUE; +} + +static +inline +void +ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event) +{ + STATIC_CONTRACT_NOTHROW; + wait_event->event = NULL; +} + +static +inline +bool +ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event) +{ + STATIC_CONTRACT_NOTHROW; + return true; +} + +static +inline +int32_t +ep_rt_wait_event_wait ( + ep_rt_wait_event_handle_t *wait_event, + uint32_t timeout, + bool alertable) +{ + STATIC_CONTRACT_NOTHROW; + EP_ASSERT (wait_event != NULL && wait_event->event == (CLREventStatic *)INVALID_HANDLE_VALUE); + return (int32_t)0; +} + +static +inline +EventPipeWaitHandle +ep_rt_wait_event_get_wait_handle (ep_rt_wait_event_handle_t *wait_event) +{ + STATIC_CONTRACT_NOTHROW; + EP_ASSERT (wait_event != NULL); + return (EventPipeWaitHandle)wait_event->event; +} + +static +inline +bool +ep_rt_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) +{ + STATIC_CONTRACT_NOTHROW; + if (wait_event == NULL || wait_event->event == NULL || wait_event->event != (CLREventStatic *)INVALID_HANDLE_VALUE) + return false; + return true; +} + +#endif // PERFTRACING_DISABLE_THREADS + + /* * Misc. */ @@ -851,6 +932,7 @@ typedef struct _rt_coreclr_thread_params_internal_t { #undef EP_RT_DEFINE_THREAD_FUNC #define EP_RT_DEFINE_THREAD_FUNC(name) static ep_rt_thread_start_func_return_t WINAPI name (LPVOID data) +#ifndef PERFTRACING_DISABLE_THREADS EP_RT_DEFINE_THREAD_FUNC (ep_rt_thread_coreclr_start_func) { STATIC_CONTRACT_NOTHROW; @@ -934,9 +1016,48 @@ ep_rt_queue_job ( void *job_func, void *params) { - EP_UNREACHABLE ("Not implemented in CoreCLR"); + EP_UNREACHABLE ("Not implemented in multi-threaded"); + return false; +} + +#else // PERFTRACING_DISABLE_THREADS + +static +inline +bool +ep_rt_thread_create ( + void *thread_func, + void *params, + EventPipeThreadType thread_type, + void *id) +{ + EP_UNREACHABLE ("Not implemented in single-threaded"); + return false; +} + +#ifdef HOST_BROWSER +#include "wasm/entrypoints.h" +typedef size_t (*ep_rt_job_cb_t)(void *data); +#endif + +static +bool +ep_rt_queue_job ( + void *job_func, + void *params) +{ +#ifdef HOST_BROWSER + // In single-threaded mode the job runs on the browser event loop + SystemJS_DiagnosticServerQueueJob ((ep_rt_job_cb_t)job_func, params); + return true; +#else + EP_UNREACHABLE ("Not implemented on this platform"); + return false; +#endif } +#endif // PERFTRACING_DISABLE_THREADS + static inline void @@ -950,6 +1071,7 @@ inline void ep_rt_thread_sleep (uint64_t ns) { +#ifndef PERFTRACING_DISABLE_THREADS STATIC_CONTRACT_NOTHROW; #ifdef TARGET_UNIX @@ -958,6 +1080,7 @@ ep_rt_thread_sleep (uint64_t ns) const uint32_t NUM_NANOSECONDS_IN_1_MS = 1000000; ClrSleepEx (static_cast(ns / NUM_NANOSECONDS_IN_1_MS), FALSE); #endif //TARGET_UNIX +#endif // PERFTRACING_DISABLE_THREADS } static diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index cd4cff43f3c88d..53edc1c17933cd 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -50,11 +50,16 @@ DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context }; DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context }; DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { &MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_Context, MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context }; -#else +#elif defined(FEATURE_EVENTSOURCE_XPLAT) DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_LTTNG_Context }; DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_LTTNG_Context }; DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_LTTNG_Context }; DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context, &MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_LTTNG_Context }; +#else +DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context }; +DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context }; +DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context }; +DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context = { MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context }; #endif // HOST_UNIX #ifdef FEATURE_NATIVEAOT @@ -2277,9 +2282,9 @@ void InitializeEventTracing() // providers can do so now ETW::TypeSystemLog::PostRegistrationInit(); -#if defined(HOST_UNIX) && defined (FEATURE_PERFTRACING) +#if defined(FEATURE_EVENTSOURCE_XPLAT) XplatEventLogger::InitializeLogger(); -#endif // HOST_UNIX && FEATURE_PERFTRACING +#endif // FEATURE_EVENTSOURCE_XPLAT } // Plumbing to funnel event pipe callbacks and ETW callbacks together into a single common @@ -5607,10 +5612,10 @@ bool EventPipeHelper::IsEnabled(DOTNET_TRACE_CONTEXT Context, UCHAR Level, ULONG } #endif // FEATURE_PERFTRACING -#if defined(HOST_UNIX) && defined(FEATURE_PERFTRACING) +#if defined(FEATURE_EVENTSOURCE_XPLAT) // This is a wrapper method for LTTng. See https://github.com/dotnet/coreclr/pull/27273 for details. extern "C" bool XplatEventLoggerIsEnabled() { return XplatEventLogger::IsEventLoggingEnabled(); } -#endif // HOST_UNIX && FEATURE_PERFTRACING +#endif // FEATURE_EVENTSOURCE_XPLAT diff --git a/src/coreclr/vm/eventtrace_bulktype.cpp b/src/coreclr/vm/eventtrace_bulktype.cpp index 3b148be7627a07..4eac600acfa2c4 100644 --- a/src/coreclr/vm/eventtrace_bulktype.cpp +++ b/src/coreclr/vm/eventtrace_bulktype.cpp @@ -420,9 +420,11 @@ void BulkStaticsLogger::FireBulkStaticsEvent() EventDataDescCreate(&eventData[3], m_buffer, m_used); ULONG result = EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &GCBulkRootStaticVar, ARRAY_SIZE(eventData), eventData); -#else +#elif defined(FEATURE_EVENTSOURCE_XPLAT) ULONG result = FireEtXplatGCBulkRootStaticVar(m_count, appDomain, instance, m_used, m_buffer); -#endif //!defined(HOST_UNIX) +#else + ULONG result = ERROR_SUCCESS; +#endif result |= EventPipeWriteEventGCBulkRootStaticVar(m_count, appDomain, instance, m_used, m_buffer); _ASSERTE(result == ERROR_SUCCESS); diff --git a/src/coreclr/vm/eventtrace_gcheap.cpp b/src/coreclr/vm/eventtrace_gcheap.cpp index d8b395941218f8..2c9c3df6e2f473 100644 --- a/src/coreclr/vm/eventtrace_gcheap.cpp +++ b/src/coreclr/vm/eventtrace_gcheap.cpp @@ -408,6 +408,24 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN delete pContext; } +#if defined(TARGET_BROWSER) +#include "wasm/entrypoints.h" + +static size_t ForceGCForDiagnosticsJob(void* data) +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + ETW::GCLog::ForceGCForDiagnostics(); + return 1; // done +} +#endif // TARGET_BROWSER + // This implements the public runtime provider's GCHeapCollectKeyword. It // performs a full, gen-2, blocking GC. VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) @@ -427,7 +445,14 @@ VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) InterlockedExchange64(&s_l64LastClientSequenceNumber, l64ClientSequenceNumber); +#if defined(TARGET_BROWSER) + // On single-threaded browser, we cannot call ForceGCForDiagnostics synchronously + // from within the provider callback (which runs during ep_enable_3 under the + // EventPipe lock). Defer the GC to the next event loop turn. + SystemJS_DiagnosticServerQueueJob(ForceGCForDiagnosticsJob, NULL); +#else ForceGCForDiagnostics(); +#endif // TARGET_BROWSER } //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index f1b400afbbac6c..d65fb6b022419d 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -878,7 +878,7 @@ void GCToEEInterface::DiagUpdateGenerationBounds() void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) { -#ifdef GC_PROFILING +#if defined(GC_PROFILING) || defined(PERFTRACING_DISABLE_THREADS) // We were only doing generation bounds and GC finish callback for non concurrent GCs so // I am keeping that behavior to not break profilers. But if BasicGC monitoring is enabled // we will do these for all GCs. @@ -886,7 +886,9 @@ void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurr { GCProfileWalkHeap(false); } +#endif // defined(GC_PROFILING) || defined(PERFTRACING_DISABLE_THREADS) +#ifdef GC_PROFILING if (CORProfilerTrackBasicGC() || (!fConcurrent && CORProfilerTrackGC())) { DiagUpdateGenerationBounds(); diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 849e33a9cf07b9..08980a9ddf67e2 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -298,6 +298,12 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I64(2)); } + static void CallFunc_I32_I32_I64_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int32_t, int32_t, int64_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int64_t, int32_t, int32_t, int32_t, int32_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I64(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6)); + } + NOINLINE static void CallFunc_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; @@ -342,6 +348,18 @@ namespace *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } + static void CallFunc_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int64_t) = (int32_t (*)(int64_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I64(0)); + } + + static void CallFunc_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int64_t, int32_t) = (int32_t (*)(int64_t, int32_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1)); + } + static void CallFunc_I64_I32_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int64_t, int32_t, int64_t, int32_t) = (int32_t (*)(int64_t, int32_t, int64_t, int32_t))pcode; @@ -373,6 +391,12 @@ namespace *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2)); } + static void CallFunc_I32_I32_I32_I32_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int64_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int64_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; + *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); + } + static void CallFunc_I32_I32_I32_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int32_t, int32_t, int64_t) = (int64_t (*)(int32_t, int32_t, int32_t, int64_t))pcode; @@ -493,6 +517,24 @@ namespace (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint); } + static void CallFunc_F64_F64_F64_F64_F64_F64_F64_F64_F64_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + void (*fptr)(double, double, double, double, double, double, double, double, double, int32_t, int32_t) = (void (*)(double, double, double, double, double, double, double, double, double, int32_t, int32_t))pcode; + (*fptr)(ARG_F64(0), ARG_F64(1), ARG_F64(2), ARG_F64(3), ARG_F64(4), ARG_F64(5), ARG_F64(6), ARG_F64(7), ARG_F64(8), ARG_I32(9), ARG_I32(10)); + } + + static void CallFunc_F64_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + void (*fptr)(double, int32_t) = (void (*)(double, int32_t))pcode; + (*fptr)(ARG_F64(0), ARG_I32(1)); + } + + static void CallFunc_F64_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + void (*fptr)(double, int32_t, int32_t, int32_t) = (void (*)(double, int32_t, int32_t, int32_t))pcode; + (*fptr)(ARG_F64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); + } + NOINLINE static void CallFunc_F64_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; @@ -537,6 +579,12 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_IND(3), ARG_I32(4), ARG_I32(5)); } + static void CallFunc_I32_I32_F64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + void (*fptr)(int32_t, int32_t, double) = (void (*)(int32_t, int32_t, double))pcode; + (*fptr)(ARG_I32(0), ARG_I32(1), ARG_F64(2)); + } + static void CallFunc_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; @@ -573,6 +621,12 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } + static void CallFunc_I32_I32_I32_I32_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + void (*fptr)(int32_t, int32_t, int32_t, int32_t, int64_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int64_t))pcode; + (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I64(4)); + } + NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet) { alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK; @@ -653,6 +707,7 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "Miiiil", (void*)&CallFunc_I32_I32_I32_I64_RetI32 }, { "Miiiip", (void*)&CallFunc_I32_I32_I32_RetI32_PE }, { "Miiil", (void*)&CallFunc_I32_I32_I64_RetI32 }, + { "Miiiliiii", (void*)&CallFunc_I32_I32_I64_I32_I32_I32_I32_RetI32 }, { "Miiip", (void*)&CallFunc_I32_I32_RetI32_PE }, { "Miil", (void*)&CallFunc_I32_I64_RetI32 }, { "Miili", (void*)&CallFunc_I32_I64_I32_RetI32 }, @@ -660,11 +715,14 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "Miill", (void*)&CallFunc_I32_I64_I64_RetI32 }, { "Miilli", (void*)&CallFunc_I32_I64_I64_I32_RetI32 }, { "Miip", (void*)&CallFunc_I32_RetI32_PE }, + { "Mil", (void*)&CallFunc_I64_RetI32 }, + { "Mili", (void*)&CallFunc_I64_I32_RetI32 }, { "Milili", (void*)&CallFunc_I64_I32_I64_I32_RetI32 }, { "Mip", (void*)&CallFunc_Void_RetI32_PE }, { "Ml", (void*)&CallFunc_Void_RetI64 }, { "Mli", (void*)&CallFunc_I32_RetI64 }, { "Mliii", (void*)&CallFunc_I32_I32_I32_RetI64 }, + { "Mliiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetI64 }, { "Mliiil", (void*)&CallFunc_I32_I32_I32_I64_RetI64 }, { "Mlili", (void*)&CallFunc_I32_I64_I32_RetI64 }, { "Mlillp", (void*)&CallFunc_I32_I64_I64_RetI64_PE }, @@ -684,6 +742,9 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "MvS8iiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_RetVoid }, { "MvS8iiiiiiiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid }, { "MvTp", (void*)&CallFunc_This_RetVoid_PE }, + { "Mvdddddddddii", (void*)&CallFunc_F64_F64_F64_F64_F64_F64_F64_F64_F64_I32_I32_RetVoid }, + { "Mvdi", (void*)&CallFunc_F64_I32_RetVoid }, + { "Mvdiii", (void*)&CallFunc_F64_I32_I32_I32_RetVoid }, { "Mvdiip", (void*)&CallFunc_F64_I32_I32_RetVoid_PE }, { "Mvfiip", (void*)&CallFunc_F32_I32_I32_RetVoid_PE }, { "Mvi", (void*)&CallFunc_I32_RetVoid }, @@ -691,12 +752,14 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "Mvii", (void*)&CallFunc_I32_I32_RetVoid }, { "MviiS8S8i", (void*)&CallFunc_I32_I32_S8_S8_I32_RetVoid }, { "MviiS8S8ii", (void*)&CallFunc_I32_I32_S8_S8_I32_I32_RetVoid }, + { "Mviid", (void*)&CallFunc_I32_I32_F64_RetVoid }, { "Mviii", (void*)&CallFunc_I32_I32_I32_RetVoid }, { "MviiiS8S8", (void*)&CallFunc_I32_I32_I32_S8_S8_RetVoid }, { "MviiiS8S8i", (void*)&CallFunc_I32_I32_I32_S8_S8_I32_RetVoid }, { "Mviiii", (void*)&CallFunc_I32_I32_I32_I32_RetVoid }, { "Mviiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetVoid }, { "Mviiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetVoid }, + { "Mviiiil", (void*)&CallFunc_I32_I32_I32_I32_I64_RetVoid }, { "Mviiip", (void*)&CallFunc_I32_I32_I32_RetVoid_PE }, { "Mviip", (void*)&CallFunc_I32_I32_RetVoid_PE }, { "Mvip", (void*)&CallFunc_I32_RetVoid_PE }, diff --git a/src/coreclr/vm/wasm/callhelpers-reverse.cpp b/src/coreclr/vm/wasm/callhelpers-reverse.cpp index 4c154ed1fe46e4..e690a467933715 100644 --- a/src/coreclr/vm/wasm/callhelpers-reverse.cpp +++ b/src/coreclr/vm/wasm/callhelpers-reverse.cpp @@ -162,6 +162,19 @@ static void Call_System_Private_CoreLib_System_Runtime_CompilerServices_RuntimeH ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Runtime_CompilerServices_RuntimeHelpers_CallToString_I32_I32_I32_RetVoid, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_System_Private_CoreLib_System_Runtime_CompilerServices_RuntimeHelpers_CallToString_I32_I32_I32_RetVoid); } +static MethodDesc* MD_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid(void * arg0, int32_t arg1, uint32_t arg2, int64_t arg3, int64_t arg4, void * arg5, void * arg6) +{ + int64_t args[7] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2, (int64_t)arg3, (int64_t)arg4, (int64_t)arg5, (int64_t)arg6 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid) + { + LookupUnmanagedCallersOnlyMethodByName("System.Diagnostics.Tracing.EventPipeEventProvider, System.Private.CoreLib", "Callback", &MD_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid); +} + static MethodDesc* MD_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearManaged_I32_I32_I32_I32_RetVoid = nullptr; static void Call_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearManaged_I32_I32_I32_I32_RetVoid(void * arg0, void * arg1, void * arg2, void * arg3) { @@ -1181,6 +1194,7 @@ const ReverseThunkMapEntry g_ReverseThunks[] = { 433365813, "CallJSExport#2:System.Runtime.InteropServices.JavaScript:System.Runtime.InteropServices.JavaScript:JavaScriptExports", { &MD_System_Runtime_InteropServices_JavaScript_System_Runtime_InteropServices_JavaScript_JavaScriptExports_CallJSExport_I32_I32_RetVoid, (void*)&Call_System_Runtime_InteropServices_JavaScript_System_Runtime_InteropServices_JavaScript_JavaScriptExports_CallJSExport_I32_I32_RetVoid } }, { 1821934012, "CallStartupHook#2:System.Private.CoreLib:System:StartupHookProvider", { &MD_System_Private_CoreLib_System_StartupHookProvider_CallStartupHook_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_StartupHookProvider_CallStartupHook_I32_I32_RetVoid } }, { 2915047114, "CallToString#3:System.Private.CoreLib:System.Runtime.CompilerServices:RuntimeHelpers", { &MD_System_Private_CoreLib_System_Runtime_CompilerServices_RuntimeHelpers_CallToString_I32_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_Runtime_CompilerServices_RuntimeHelpers_CallToString_I32_I32_I32_RetVoid } }, + { 4077371982, "Callback#7:System.Private.CoreLib:System.Diagnostics.Tracing:EventPipeEventProvider", { &MD_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_Diagnostics_Tracing_EventPipeEventProvider_Callback_I32_I32_I32_I64_I64_I32_I32_RetVoid } }, { 3358042195, "ClearManaged#4:System.Private.CoreLib:System.StubHelpers:MngdRefCustomMarshaler", { &MD_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearManaged_I32_I32_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearManaged_I32_I32_I32_I32_RetVoid } }, { 2311968855, "ClearNative#4:System.Private.CoreLib:System.StubHelpers:MngdRefCustomMarshaler", { &MD_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearNative_I32_I32_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_StubHelpers_MngdRefCustomMarshaler_ClearNative_I32_I32_I32_I32_RetVoid } }, { 3113228365, "CompleteTask#1:System.Runtime.InteropServices.JavaScript:System.Runtime.InteropServices.JavaScript:JavaScriptExports", { &MD_System_Runtime_InteropServices_JavaScript_System_Runtime_InteropServices_JavaScript_JavaScriptExports_CompleteTask_I32_RetVoid, (void*)&Call_System_Runtime_InteropServices_JavaScript_System_Runtime_InteropServices_JavaScript_JavaScriptExports_CompleteTask_I32_RetVoid } }, diff --git a/src/coreclr/vm/wasm/entrypoints.h b/src/coreclr/vm/wasm/entrypoints.h index d53de7e63df3d1..3f71598b8715d6 100644 --- a/src/coreclr/vm/wasm/entrypoints.h +++ b/src/coreclr/vm/wasm/entrypoints.h @@ -13,6 +13,7 @@ extern "C" void SystemJS_ResolveMainPromise(int exitCode); extern "C" void SystemJS_RejectMainPromise(const char16_t *message, int messageLength, const char16_t *stackTrace, int stackTraceLength); extern "C" void SystemJS_ScheduleTimer(int shortestDueTimeMs); extern "C" void SystemJS_ScheduleBackgroundJob(); +extern "C" void SystemJS_DiagnosticServerQueueJob(size_t (*cb)(void *data), void *data); #endif diff --git a/src/coreclr/vm/wks/CMakeLists.txt b/src/coreclr/vm/wks/CMakeLists.txt index 25399d9b1e751f..bb69aec244f907 100644 --- a/src/coreclr/vm/wks/CMakeLists.txt +++ b/src/coreclr/vm/wks/CMakeLists.txt @@ -67,6 +67,10 @@ target_compile_definitions(cee_wks_mergeable PUBLIC CORECLR_EMBEDDED) target_compile_definitions(cee_wks_core PRIVATE GC_DESCRIPTOR) +if (FEATURE_PERFTRACING_DISABLE_THREADS) + target_compile_definitions(cee_wks_core PRIVATE PERFTRACING_DISABLE_THREADS) +endif() + if (CLR_CMAKE_HOST_WIN32) link_natvis_sources_for_target(cee_wks INTERFACE ../vm.natvis) link_natvis_sources_for_target(cee_wks_mergeable INTERFACE ../vm.natvis) diff --git a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj index e5ce9d7789566a..1789b2304a360f 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj +++ b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj @@ -7,12 +7,14 @@ true false + $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) + $(NoWarn);WASM0066 - + true - + diff --git a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets index 40b486404316fd..068b1bfa856b98 100644 --- a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets +++ b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets @@ -91,6 +91,7 @@ NativeLibrary items are converted to NativeFileReference items later in the flow (in _CoreCLRPrepareForNativeBuild) so we have to inspect both here. --> true + true diff --git a/src/native/libs/Common/JavaScript/types/ems-ambient.ts b/src/native/libs/Common/JavaScript/types/ems-ambient.ts index 0f394656c9c632..0b31a52dce3b04 100644 --- a/src/native/libs/Common/JavaScript/types/ems-ambient.ts +++ b/src/native/libs/Common/JavaScript/types/ems-ambient.ts @@ -29,7 +29,7 @@ export type EmsAmbientSymbolsType = EmscriptenModuleInternal & { _SystemJS_ExecuteBackgroundJobCallback: () => void; _SystemJS_ExecuteFinalizationCallback: () => void; _SystemJS_ExecuteDiagnosticServerCallback: () => void; - _SystemJS_ScheduleDiagnosticServer: () => void; + _SystemJS_ScheduleDiagnosticServer: (delayMs: number) => void; _BrowserHost_CreateHostContract: () => VoidPtr; _BrowserHost_InitializeDotnet: (propertiesCount: number, propertyKeys: CharPtrPtr, propertyValues: CharPtrPtr) => number; _BrowserHost_ExecuteAssembly: (mainAssemblyNamePtr: number, argsLength: number, argsPtr: number) => number; diff --git a/src/native/libs/System.Native.Browser/diagnostic_server_jobs.c b/src/native/libs/System.Native.Browser/diagnostic_server_jobs.c index 4bda75186dcb51..cbee13f3a5d83a 100644 --- a/src/native/libs/System.Native.Browser/diagnostic_server_jobs.c +++ b/src/native/libs/System.Native.Browser/diagnostic_server_jobs.c @@ -8,7 +8,7 @@ #include "diagnostic_server_jobs.h" -extern void SystemJS_ScheduleDiagnosticServer(void); +extern void SystemJS_ScheduleDiagnosticServer(int delayMs); typedef struct DsJobNode { ds_job_cb cb; @@ -32,7 +32,7 @@ SystemJS_DiagnosticServerQueueJob (ds_job_cb cb, void *data) node->next = jobs; jobs = node; if (wasEmpty) { - SystemJS_ScheduleDiagnosticServer (); + SystemJS_ScheduleDiagnosticServer (0); } } @@ -56,6 +56,6 @@ SystemJS_ExecuteDiagnosticServerCallback (void) } if (jobs) { - SystemJS_ScheduleDiagnosticServer (); + SystemJS_ScheduleDiagnosticServer (100); } } diff --git a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts index 22384640be5328..8e7a6410255125 100644 --- a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts +++ b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-js.ts @@ -87,7 +87,7 @@ class DiagnosticSession extends DiagnosticConnectionBase implements IDiagnosticC // this is message from the diagnostic server, which is dotnet VM in this browser send(message: Uint8Array): number { - dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(); + dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(0); if (this.isAdvertMessage(message)) { // eslint-disable-next-line @typescript-eslint/no-this-alias serverSession = this; @@ -119,7 +119,7 @@ class DiagnosticSession extends DiagnosticConnectionBase implements IDiagnosticC // this is message to the diagnostic server, which is dotnet VM in this browser respond(message: Uint8Array): void { this.messagesReceived.push(message); - dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(); + dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(0); } close(): number { diff --git a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-ws.ts b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-ws.ts index 28b84362b966ee..f6c3c42b522008 100644 --- a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-ws.ts +++ b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server-ws.ts @@ -41,7 +41,7 @@ class DiagnosticConnectionWS extends DiagnosticConnectionBase implements IDiagno } send(message: Uint8Array): number { - dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(); + dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(0); // copy the message if (this.ws!.readyState == WebSocket.CLOSED || this.ws!.readyState == WebSocket.CLOSING) { return -1; @@ -61,7 +61,7 @@ class DiagnosticConnectionWS extends DiagnosticConnectionBase implements IDiagno } close(): number { - dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(); + dotnetNativeBrowserExports.SystemJS_ScheduleDiagnosticServer(0); this.ws.close(); return 0; } diff --git a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server.ts b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server.ts index 4a59c891e53381..5c6d3c5bbd1c94 100644 --- a/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server.ts +++ b/src/native/libs/System.Native.Browser/diagnostics/diagnostic-server.ts @@ -8,6 +8,7 @@ import { createDiagConnectionWs } from "./diagnostic-server-ws"; import { advertise } from "./client-commands"; import { IDiagnosticConnection } from "./types"; import { dotnetApi, Module } from "./cross-module"; +import { ENVIRONMENT_IS_WEB } from "./per-module"; let socketHandles: Map = undefined as any; let nextSocketHandle = 1; @@ -93,7 +94,7 @@ export function initializeDS() { const loaderConfig = dotnetApi.getConfig(); const diagnosticPorts = "DOTNET_DiagnosticPorts"; loaderConfig.environmentVariables ??= {}; - if (loaderConfig.environmentVariables![diagnosticPorts] === undefined) { + if (ENVIRONMENT_IS_WEB && loaderConfig.environmentVariables![diagnosticPorts] === undefined) { loaderConfig.environmentVariables![diagnosticPorts] = "js://ready"; } initializeJsClient(); diff --git a/src/native/libs/System.Native.Browser/native/scheduling.ts b/src/native/libs/System.Native.Browser/native/scheduling.ts index 09708677dfaf64..45b71570f2b37a 100644 --- a/src/native/libs/System.Native.Browser/native/scheduling.ts +++ b/src/native/libs/System.Native.Browser/native/scheduling.ts @@ -81,17 +81,20 @@ export function SystemJS_ScheduleFinalization(): void { } } -export function SystemJS_ScheduleDiagnosticServer(): void { +export function SystemJS_ScheduleDiagnosticServer(delayMs: number): void { if (_ems_.ABORT || _ems_.DOTNET.isAborting) { // runtime is shutting down return; } + if (delayMs !== 0 && (_ems_.ENVIRONMENT_IS_SHELL || _ems_.DOTNET.lastScheduledDiagnosticServerId)) { + return; + } if (_ems_.DOTNET.lastScheduledDiagnosticServerId) { globalThis.clearTimeout(_ems_.DOTNET.lastScheduledDiagnosticServerId); _ems_.runtimeKeepalivePop(); _ems_.DOTNET.lastScheduledDiagnosticServerId = undefined; } - _ems_.DOTNET.lastScheduledDiagnosticServerId = _ems_.safeSetTimeout(SystemJS_ScheduleDiagnosticServerTick, 0); + _ems_.DOTNET.lastScheduledDiagnosticServerId = _ems_.safeSetTimeout(SystemJS_ScheduleDiagnosticServerTick, delayMs); function SystemJS_ScheduleDiagnosticServerTick(): void { try {