From 2e146671d19f3ba4d79c8b5133899c5e5b1eba24 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 29 May 2026 07:38:50 +0200 Subject: [PATCH 01/11] split --- src/coreclr/clr.featuredefines.props | 2 - src/coreclr/clrdefinitions.cmake | 9 +- src/coreclr/clrfeatures.cmake | 10 +- src/coreclr/inc/eventtracebase.h | 11 +- src/coreclr/interpreter/CMakeLists.txt | 4 + src/coreclr/scripts/genEventPipe.py | 28 +++- src/coreclr/scripts/genEventing.py | 26 +++- src/coreclr/vm/eventing/CMakeLists.txt | 9 +- .../vm/eventing/eventpipe/CMakeLists.txt | 5 + .../vm/eventing/eventpipe/ep-rt-coreclr.h | 127 +++++++++++++++++- src/coreclr/vm/eventtrace.cpp | 13 +- src/coreclr/vm/eventtrace_bulktype.cpp | 6 +- src/coreclr/vm/eventtrace_gcheap.cpp | 25 ++++ src/coreclr/vm/gcenv.ee.cpp | 4 +- .../vm/wasm/callhelpers-interp-to-managed.cpp | 63 +++++++++ src/coreclr/vm/wasm/callhelpers-reverse.cpp | 14 ++ src/coreclr/vm/wks/CMakeLists.txt | 4 + .../tests/BasicEventSourceTest/TestsWrite.cs | 5 +- .../BasicEventSourceTest/TestsWriteEvent.cs | 2 + .../System.Diagnostics.Tracing.Tests.csproj | 11 +- .../build/BrowserWasmApp.CoreCLR.targets | 1 + .../corehost/browserhost/CMakeLists.txt | 2 + 22 files changed, 345 insertions(+), 36 deletions(-) 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..45744c7e2b0127 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -24,7 +24,7 @@ if(CLR_CMAKE_TARGET_TIZEN_LINUX) endif() 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() @@ -37,9 +37,11 @@ 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) +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..ea0947e83ca1af 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -121,6 +121,12 @@ enum EtwGCSettingFlags #define ETWFireEvent(EventName) FireEtw##EventName(GetClrInstanceId()) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) +#if defined(HOST_BROWSER) || defined(HOST_WASI) +#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)) +#else // HOST_BROWSER || HOST_WASI #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 +134,7 @@ 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))) +#endif // HOST_BROWSER || HOST_WASI #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) #else //defined(FEATURE_PERFTRACING) #define ETW_INLINE @@ -416,7 +423,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(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) class XplatEventLoggerController { @@ -557,7 +564,7 @@ class XplatEventLogger }; -#endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#endif // defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && (defined(FEATURE_EVENT_TRACE) || 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..2fa69e70836cac 100644 --- a/src/coreclr/scripts/genEventPipe.py +++ b/src/coreclr/scripts/genEventPipe.py @@ -181,12 +181,28 @@ def generateClrEventPipeWriteEventsImpl( "void Init" + providerPrettyName + "(void)\n{\n") - WriteEventImpl.append( - " EventPipeProvider" + - providerPrettyName + - " = " + createProviderFunc + "(" + - providerPrettyName + - "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\n") + if runtimeFlavor.coreclr: + WriteEventImpl.append( + "#ifdef FEATURE_EVENT_TRACE\n" + + " EventPipeProvider" + + providerPrettyName + + " = " + createProviderFunc + "(" + + providerPrettyName + + "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\n" + + "#else\n" + + " EventPipeProvider" + + providerPrettyName + + " = " + createProviderFunc + "(" + + providerPrettyName + + "Name, nullptr);\n" + + "#endif\n") + else: + WriteEventImpl.append( + " EventPipeProvider" + + providerPrettyName + + " = " + createProviderFunc + "(" + + providerPrettyName + + "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\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..809599d91a59bc 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(HOST_BROWSER) && !defined(HOST_WASI)\n") + clrallEvents.append(" || (XplatEventLogger" + ("::" if target_cpp else "_") + "IsEventLoggingEnabled() && EventXplatEnabled" + - eventName + "());}\n\n") + eventName + "())\n") + clrallEvents.append("#endif // !HOST_BROWSER && !HOST_WASI\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(HOST_BROWSER) && !defined(HOST_WASI)\n") fnbody.append(lindent) fnbody.append("status &= FireEtXplat" + eventName + "(" + ''.join(line) + ");\n") + if not is_host_windows: + fnbody.append("#endif // !HOST_BROWSER && !HOST_WASI\n") if runtimeFlavor.nativeaot: if providerName == "Microsoft-Windows-DotNETRuntime" or providerName == "Microsoft-Windows-DotNETRuntimePrivate" or providerName == "Microsoft-Windows-DotNETRuntimeRundown": @@ -865,11 +872,18 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern dotnet_trace_context_typedef_unix = """ #if !defined(DOTNET_TRACE_CONTEXT_DEF) #define DOTNET_TRACE_CONTEXT_DEF +#if defined(HOST_BROWSER) || defined(HOST_WASI) +typedef struct _DOTNET_TRACE_CONTEXT +{ + EVENTPIPE_TRACE_CONTEXT EventPipeProvider; +} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; +#else typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; PLTTNG_TRACE_CONTEXT LttngProvider; } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; +#endif #endif // DOTNET_TRACE_CONTEXT_DEF """ @@ -894,7 +908,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(HOST_BROWSER) && !defined(HOST_WASI)\n") Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT + Clrproviders.write("#endif // !HOST_BROWSER && !HOST_WASI\n") Clrproviders.write(dotnet_trace_context_typedef_unix + "\n") allProviders = [] @@ -910,7 +926,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(HOST_BROWSER) && !defined(HOST_WASI)\n') Clrproviders.write('__attribute__((weak)) LTTNG_TRACE_CONTEXT ' + lttngProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + Clrproviders.write('#endif // !HOST_BROWSER && !HOST_WASI\n') Clrproviders.write("// Keywords\n"); for keywordNode in providerNode.getElementsByTagName('keyword'): @@ -934,10 +952,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(HOST_BROWSER) && !defined(HOST_WASI)\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 // !HOST_BROWSER && !HOST_WASI\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..70f4a8ea43d03b 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,71 @@ ep_rt_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) return wait_event->event->IsValid (); } +#else // PERFTRACING_DISABLE_THREADS + +static +inline +void +ep_rt_wait_event_alloc ( + ep_rt_wait_event_handle_t *wait_event, + bool manual, + bool initial) +{ + 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) +{ + wait_event->event = NULL; +} + +static +inline +bool +ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event) +{ + return true; +} + +static +inline +int32_t +ep_rt_wait_event_wait ( + ep_rt_wait_event_handle_t *wait_event, + uint32_t timeout, + bool alertable) +{ + 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) +{ + 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) +{ + if (wait_event == NULL || wait_event->event == NULL || wait_event->event != (CLREventStatic *)INVALID_HANDLE_VALUE) + return false; + else + return true; +} + +#endif // PERFTRACING_DISABLE_THREADS + + /* * Misc. */ @@ -851,6 +924,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 +1008,58 @@ ep_rt_queue_job ( void *job_func, void *params) { - EP_UNREACHABLE ("Not implemented in CoreCLR"); + EP_UNREACHABLE ("Not implemented on 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 on in single threaded"); + return false; +} + +#ifdef HOST_BROWSER +typedef size_t (*ep_rt_job_cb_t)(void *data); +extern "C" void SystemJS_DiagnosticServerQueueJob (ep_rt_job_cb_t cb, void *data); +#endif + +static +bool +ep_rt_queue_job ( + void *job_func, + void *params) +{ +#ifdef HOST_BROWSER + // in single-threaded, it will run the callback inline and re-schedule itself if necessary + // it's called from browser event loop + ep_rt_job_cb_t cb = (ep_rt_job_cb_t)job_func; + + // invoke the callback inline for the first time + size_t done = cb (params); + + // see if it's done or needs to be scheduled again + if (!done) { + // self schedule again + SystemJS_DiagnosticServerQueueJob (cb, params); + } + + return true; +#else + EP_UNREACHABLE ("Not implemented on this platform"); +#endif } +#endif // PERFTRACING_DISABLE_THREADS + static inline void @@ -950,6 +1073,7 @@ inline void ep_rt_thread_sleep (uint64_t ns) { +#ifndef PERFTRACING_DISABLE_THREADS STATIC_CONTRACT_NOTHROW; #ifdef TARGET_UNIX @@ -958,6 +1082,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..ed0477256d3764 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -50,6 +50,11 @@ 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 }; +#elif defined(HOST_BROWSER) || defined(HOST_WASI) +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 }; #else 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 }; @@ -2277,9 +2282,9 @@ void InitializeEventTracing() // providers can do so now ETW::TypeSystemLog::PostRegistrationInit(); -#if defined(HOST_UNIX) && defined (FEATURE_PERFTRACING) +#if defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && defined(FEATURE_PERFTRACING) XplatEventLogger::InitializeLogger(); -#endif // HOST_UNIX && FEATURE_PERFTRACING +#endif // HOST_UNIX && !HOST_BROWSER && !HOST_WASI && FEATURE_PERFTRACING } // 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(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && defined(FEATURE_PERFTRACING) // 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 // HOST_UNIX && !HOST_BROWSER && !HOST_WASI && FEATURE_PERFTRACING diff --git a/src/coreclr/vm/eventtrace_bulktype.cpp b/src/coreclr/vm/eventtrace_bulktype.cpp index 3b148be7627a07..7d820089eecb9f 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(HOST_BROWSER) && !defined(HOST_WASI) 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..a1d415b53c4b21 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) +extern "C" void SystemJS_DiagnosticServerQueueJob(size_t (*cb)(void*), void* data); + +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..3e0bd1cfb635fc 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(FEATURE_EVENT_TRACE) // 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(FEATURE_EVENT_TRACE) +#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/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/BasicEventSourceTest/TestsWrite.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs index b5d71dacd83346..e30b30acec31e2 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs @@ -29,12 +29,13 @@ private struct PartB_UserInfo public static TheoryData GetListeners() { TheoryData data = new TheoryData(); - - if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && +#if !TARGET_BROWSER + if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && (PlatformDetection.IsNotMonoRuntime || PlatformDetection.IsMacCatalyst)) { data.Add(new EventPipeListener()); } +#endif data.Add(new EventListenerListener()); data.Add(new EventListenerListener(true)); return data; diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs index ae0d1602e8407c..e4dc4cdaa88c60 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs @@ -30,11 +30,13 @@ public static TheoryData GetListenerConfigurations() public static TheoryData GetListeners() { TheoryData data = new TheoryData(); +#if !TARGET_BROWSER if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && (PlatformDetection.IsNotMonoRuntime || PlatformDetection.IsMacCatalyst)) { data.Add(new EventPipeListener()); } +#endif data.Add(new EventListenerListener()); data.Add(new EventListenerListener(true)); return data; 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..e1eec0745a6264 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,15 @@ true false + $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) + $(NoWarn);WASM0066 - + true + $(DefineConstants);TARGET_BROWSER - + @@ -29,7 +32,6 @@ - @@ -55,7 +57,8 @@ - + + 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/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 42f72ba5c0f911..e07f2566bcae7b 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -54,6 +54,8 @@ set(SHARED_LIB_DESTINATION ${CLR_ARTIFACTS_BIN_DIR}/native/net${CMAKE_NET_CORE_APP_CURRENT_VERSION}-browser-${CMAKE_BUILD_LIBRARIES_CONFIGURATION}-wasm/sharedFramework) set(SHARED_CLR_DESTINATION ${CLR_ARTIFACTS_BIN_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_RUNTIME_CONFIGURATION}/sharedFramework) +set(CLR_LIB_DESTINATION + ${CLR_ARTIFACTS_BIN_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_RUNTIME_CONFIGURATION}/lib) # CoreCLR runtime .a libraries LIST(APPEND NATIVE_LIBS From 0f4ea3ac44debcaf5f28d64ad7ab057f57f308a4 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 29 May 2026 08:49:03 +0200 Subject: [PATCH 02/11] cleanup --- src/coreclr/scripts/genEventPipe.py | 30 +++++++------------ .../vm/eventing/eventpipe/ep-rt-coreclr.h | 20 +++++++++---- src/coreclr/vm/eventtrace_gcheap.cpp | 2 +- src/coreclr/vm/wasm/entrypoints.h | 1 + .../corehost/browserhost/CMakeLists.txt | 2 -- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/coreclr/scripts/genEventPipe.py b/src/coreclr/scripts/genEventPipe.py index 2fa69e70836cac..6f801099df02e3 100644 --- a/src/coreclr/scripts/genEventPipe.py +++ b/src/coreclr/scripts/genEventPipe.py @@ -182,27 +182,19 @@ def generateClrEventPipeWriteEventsImpl( providerPrettyName + "(void)\n{\n") if runtimeFlavor.coreclr: - WriteEventImpl.append( - "#ifdef FEATURE_EVENT_TRACE\n" + - " EventPipeProvider" + - providerPrettyName + - " = " + createProviderFunc + "(" + - providerPrettyName + - "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\n" + + callbackExpr = ("\n#ifdef FEATURE_EVENT_TRACE\n" + + " " + eventPipeCallbackCastExpr + "(" + callbackName + ")\n" + "#else\n" + - " EventPipeProvider" + - providerPrettyName + - " = " + createProviderFunc + "(" + - providerPrettyName + - "Name, nullptr);\n" + - "#endif\n") + " nullptr\n" + + "#endif\n ") else: - WriteEventImpl.append( - " EventPipeProvider" + - providerPrettyName + - " = " + createProviderFunc + "(" + - providerPrettyName + - "Name, " + eventPipeCallbackCastExpr + "(" + callbackName + "));\n") + callbackExpr = eventPipeCallbackCastExpr + "(" + callbackName + ")" + WriteEventImpl.append( + " EventPipeProvider" + + providerPrettyName + + " = " + createProviderFunc + "(" + + providerPrettyName + + "Name, " + callbackExpr + ");\n") for eventNode in eventNodes: eventName = eventNode.getAttribute('symbol') templateName = eventNode.getAttribute('template') diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 70f4a8ea43d03b..7a215bf18a5e57 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -775,6 +775,9 @@ ep_rt_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) #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 @@ -783,8 +786,9 @@ ep_rt_wait_event_alloc ( bool manual, bool initial) { + STATIC_CONTRACT_NOTHROW; EP_ASSERT (wait_event != NULL); - wait_event->event = (CLREventStatic * )INVALID_HANDLE_VALUE; + wait_event->event = (CLREventStatic *)INVALID_HANDLE_VALUE; } static @@ -792,6 +796,7 @@ inline void ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event) { + STATIC_CONTRACT_NOTHROW; wait_event->event = NULL; } @@ -800,6 +805,7 @@ inline bool ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event) { + STATIC_CONTRACT_NOTHROW; return true; } @@ -811,6 +817,7 @@ ep_rt_wait_event_wait ( uint32_t timeout, bool alertable) { + STATIC_CONTRACT_NOTHROW; EP_ASSERT (wait_event != NULL && wait_event->event == (CLREventStatic *)INVALID_HANDLE_VALUE); return (int32_t)0; } @@ -820,6 +827,7 @@ 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; } @@ -829,10 +837,10 @@ 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; - else - return true; + return true; } #endif // PERFTRACING_DISABLE_THREADS @@ -1008,7 +1016,7 @@ ep_rt_queue_job ( void *job_func, void *params) { - EP_UNREACHABLE ("Not implemented on in multi threaded"); + EP_UNREACHABLE ("Not implemented in multi-threaded"); return false; } @@ -1023,13 +1031,13 @@ ep_rt_thread_create ( EventPipeThreadType thread_type, void *id) { - EP_UNREACHABLE ("Not implemented on in single threaded"); + 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); -extern "C" void SystemJS_DiagnosticServerQueueJob (ep_rt_job_cb_t cb, void *data); #endif static diff --git a/src/coreclr/vm/eventtrace_gcheap.cpp b/src/coreclr/vm/eventtrace_gcheap.cpp index a1d415b53c4b21..2c9c3df6e2f473 100644 --- a/src/coreclr/vm/eventtrace_gcheap.cpp +++ b/src/coreclr/vm/eventtrace_gcheap.cpp @@ -409,7 +409,7 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN } #if defined(TARGET_BROWSER) -extern "C" void SystemJS_DiagnosticServerQueueJob(size_t (*cb)(void*), void* data); +#include "wasm/entrypoints.h" static size_t ForceGCForDiagnosticsJob(void* data) { 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/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index e07f2566bcae7b..42f72ba5c0f911 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -54,8 +54,6 @@ set(SHARED_LIB_DESTINATION ${CLR_ARTIFACTS_BIN_DIR}/native/net${CMAKE_NET_CORE_APP_CURRENT_VERSION}-browser-${CMAKE_BUILD_LIBRARIES_CONFIGURATION}-wasm/sharedFramework) set(SHARED_CLR_DESTINATION ${CLR_ARTIFACTS_BIN_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_RUNTIME_CONFIGURATION}/sharedFramework) -set(CLR_LIB_DESTINATION - ${CLR_ARTIFACTS_BIN_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_RUNTIME_CONFIGURATION}/lib) # CoreCLR runtime .a libraries LIST(APPEND NATIVE_LIBS From 261533a9c0fd4ea82ab00e1bd86b49e6fea2cb66 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 29 May 2026 19:55:36 +0200 Subject: [PATCH 03/11] FEATURE_EVENTSOURCE_XPLAT feedback --- src/coreclr/inc/eventtracebase.h | 27 +++++++++++---------------- src/coreclr/scripts/genEventing.py | 24 ++++++++++++------------ src/coreclr/vm/eventtrace.cpp | 20 ++++++++++---------- 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index ea0947e83ca1af..f0cdf3c9f8c5ce 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -121,12 +121,7 @@ enum EtwGCSettingFlags #define ETWFireEvent(EventName) FireEtw##EventName(GetClrInstanceId()) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) -#if defined(HOST_BROWSER) || defined(HOST_WASI) -#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)) -#else // HOST_BROWSER || HOST_WASI +#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) || \ @@ -134,7 +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))) -#endif // HOST_BROWSER || HOST_WASI +#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 @@ -255,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) @@ -423,7 +418,7 @@ class XplatEventLoggerConfiguration }; #endif // defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) -#if defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#if defined(FEATURE_EVENTSOURCE_XPLAT) class XplatEventLoggerController { @@ -564,7 +559,7 @@ class XplatEventLogger }; -#endif // defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#endif // defined(FEATURE_EVENTSOURCE_XPLAT) #if defined(FEATURE_EVENT_TRACE) diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index 809599d91a59bc..e232456164e3a5 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -441,12 +441,12 @@ def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is if not is_host_windows: # native AOT and browser/wasi do not support non-windows eventing other than via event pipe if not runtimeFlavor.nativeaot: - clrallEvents.append("\n#if !defined(HOST_BROWSER) && !defined(HOST_WASI)\n") + clrallEvents.append("\n#if defined(FEATURE_EVENTSOURCE_XPLAT)\n") clrallEvents.append(" || (XplatEventLogger" + ("::" if target_cpp else "_") + "IsEventLoggingEnabled() && EventXplatEnabled" + eventName + "())\n") - clrallEvents.append("#endif // !HOST_BROWSER && !HOST_WASI\n") + clrallEvents.append("#endif // FEATURE_EVENTSOURCE_XPLAT\n") clrallEvents.append(";}\n\n") else: clrallEvents.append(";}\n\n") @@ -538,11 +538,11 @@ def generateClrallEvents(eventNodes, allTemplates, target_cpp, runtimeFlavor, is if runtimeFlavor.coreclr or write_xplatheader: if not is_host_windows: - fnbody.append("#if !defined(HOST_BROWSER) && !defined(HOST_WASI)\n") + 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 // !HOST_BROWSER && !HOST_WASI\n") + 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": @@ -872,16 +872,16 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern dotnet_trace_context_typedef_unix = """ #if !defined(DOTNET_TRACE_CONTEXT_DEF) #define DOTNET_TRACE_CONTEXT_DEF -#if defined(HOST_BROWSER) || defined(HOST_WASI) +#if defined(FEATURE_EVENTSOURCE_XPLAT) typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; + PLTTNG_TRACE_CONTEXT LttngProvider; } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #else typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; - PLTTNG_TRACE_CONTEXT LttngProvider; } DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #endif #endif // DOTNET_TRACE_CONTEXT_DEF @@ -908,9 +908,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(HOST_BROWSER) && !defined(HOST_WASI)\n") + Clrproviders.write("#if defined(FEATURE_EVENTSOURCE_XPLAT)\n") Clrproviders.write(lttng_trace_context_typedef) # define LTTNG_TRACE_CONTEXT - Clrproviders.write("#endif // !HOST_BROWSER && !HOST_WASI\n") + Clrproviders.write("#endif // FEATURE_EVENTSOURCE_XPLAT\n") Clrproviders.write(dotnet_trace_context_typedef_unix + "\n") allProviders = [] @@ -926,9 +926,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(HOST_BROWSER) && !defined(HOST_WASI)\n') + 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 // !HOST_BROWSER && !HOST_WASI\n') + Clrproviders.write('#endif // FEATURE_EVENTSOURCE_XPLAT\n') Clrproviders.write("// Keywords\n"); for keywordNode in providerNode.getElementsByTagName('keyword'): @@ -952,12 +952,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(HOST_BROWSER) && !defined(HOST_WASI)\n') + 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 // !HOST_BROWSER && !HOST_WASI\n') + Clrproviders.write('#endif // FEATURE_EVENTSOURCE_XPLAT\n') clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h") diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index ed0477256d3764..53edc1c17933cd 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -50,16 +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 }; -#elif defined(HOST_BROWSER) || defined(HOST_WASI) -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 }; -#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 @@ -2282,9 +2282,9 @@ void InitializeEventTracing() // providers can do so now ETW::TypeSystemLog::PostRegistrationInit(); -#if defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && defined(FEATURE_PERFTRACING) +#if defined(FEATURE_EVENTSOURCE_XPLAT) XplatEventLogger::InitializeLogger(); -#endif // HOST_UNIX && !HOST_BROWSER && !HOST_WASI && FEATURE_PERFTRACING +#endif // FEATURE_EVENTSOURCE_XPLAT } // Plumbing to funnel event pipe callbacks and ETW callbacks together into a single common @@ -5612,10 +5612,10 @@ bool EventPipeHelper::IsEnabled(DOTNET_TRACE_CONTEXT Context, UCHAR Level, ULONG } #endif // FEATURE_PERFTRACING -#if defined(HOST_UNIX) && !defined(HOST_BROWSER) && !defined(HOST_WASI) && 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 && !HOST_BROWSER && !HOST_WASI && FEATURE_PERFTRACING +#endif // FEATURE_EVENTSOURCE_XPLAT From d5048ed85d318c2fba22f844f7773b21e13cf2be Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 29 May 2026 20:00:19 +0200 Subject: [PATCH 04/11] explanation --- src/coreclr/clrfeatures.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake index 45744c7e2b0127..d8f20db1d4c770 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -23,6 +23,8 @@ 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_CROSS_COMPONENTS_BUILD AND CLR_CMAKE_TARGET_ARCH_WASM)) # To actually disable FEATURE_EVENT_TRACE, also change clr.featuredefines.props @@ -30,6 +32,10 @@ if(NOT DEFINED FEATURE_EVENT_TRACE) 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,6 +43,9 @@ if(NOT DEFINED FEATURE_EVENTSOURCE_XPLAT) endif() endif(NOT DEFINED FEATURE_EVENTSOURCE_XPLAT) +# 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) From 78bd837e63149bdc5160f37b2fc07d9460160b5c Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 29 May 2026 21:51:09 +0200 Subject: [PATCH 05/11] feedback --- src/coreclr/vm/eventtrace_bulktype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/eventtrace_bulktype.cpp b/src/coreclr/vm/eventtrace_bulktype.cpp index 7d820089eecb9f..4eac600acfa2c4 100644 --- a/src/coreclr/vm/eventtrace_bulktype.cpp +++ b/src/coreclr/vm/eventtrace_bulktype.cpp @@ -420,7 +420,7 @@ void BulkStaticsLogger::FireBulkStaticsEvent() EventDataDescCreate(&eventData[3], m_buffer, m_used); ULONG result = EventWrite(Microsoft_Windows_DotNETRuntimeHandle, &GCBulkRootStaticVar, ARRAY_SIZE(eventData), eventData); -#elif !defined(HOST_BROWSER) && !defined(HOST_WASI) +#elif defined(FEATURE_EVENTSOURCE_XPLAT) ULONG result = FireEtXplatGCBulkRootStaticVar(m_count, appDomain, instance, m_used, m_buffer); #else ULONG result = ERROR_SUCCESS; From dd3c214714070692067307684f5eb621125ee74e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 1 Jun 2026 09:19:17 +0200 Subject: [PATCH 06/11] fix --- src/coreclr/inc/eventtracebase.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index f0cdf3c9f8c5ce..16cb14bf278228 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -438,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); @@ -455,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); @@ -466,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); @@ -492,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; From 63aecb8fcf2130273844ba4786b1494b27116efe Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 2 Jun 2026 18:25:26 +0200 Subject: [PATCH 07/11] feedback --- src/coreclr/scripts/genEventing.py | 9 ++------- .../tests/BasicEventSourceTest/TestsWrite.cs | 5 ++--- .../tests/BasicEventSourceTest/TestsWriteEvent.cs | 2 -- .../tests/System.Diagnostics.Tracing.Tests.csproj | 5 ++--- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index e232456164e3a5..6d4006a4c49a28 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -872,18 +872,13 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern dotnet_trace_context_typedef_unix = """ #if !defined(DOTNET_TRACE_CONTEXT_DEF) #define DOTNET_TRACE_CONTEXT_DEF -#if defined(FEATURE_EVENTSOURCE_XPLAT) typedef struct _DOTNET_TRACE_CONTEXT { EVENTPIPE_TRACE_CONTEXT EventPipeProvider; +#if defined(FEATURE_EVENTSOURCE_XPLAT) PLTTNG_TRACE_CONTEXT LttngProvider; -} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; -#else -typedef struct _DOTNET_TRACE_CONTEXT -{ - EVENTPIPE_TRACE_CONTEXT EventPipeProvider; -} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #endif +} DOTNET_TRACE_CONTEXT, *PDOTNET_TRACE_CONTEXT; #endif // DOTNET_TRACE_CONTEXT_DEF """ diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs index e30b30acec31e2..b5d71dacd83346 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWrite.cs @@ -29,13 +29,12 @@ private struct PartB_UserInfo public static TheoryData GetListeners() { TheoryData data = new TheoryData(); -#if !TARGET_BROWSER - if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && + + if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && (PlatformDetection.IsNotMonoRuntime || PlatformDetection.IsMacCatalyst)) { data.Add(new EventPipeListener()); } -#endif data.Add(new EventListenerListener()); data.Add(new EventListenerListener(true)); return data; diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs index e4dc4cdaa88c60..ae0d1602e8407c 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEvent.cs @@ -30,13 +30,11 @@ public static TheoryData GetListenerConfigurations() public static TheoryData GetListeners() { TheoryData data = new TheoryData(); -#if !TARGET_BROWSER if (PlatformDetection.IsNetCore && PlatformDetection.IsNotAndroid && PlatformDetection.IsNotBrowser && (PlatformDetection.IsNotMonoRuntime || PlatformDetection.IsMacCatalyst)) { data.Add(new EventPipeListener()); } -#endif data.Add(new EventListenerListener()); data.Add(new EventListenerListener(true)); return data; 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 e1eec0745a6264..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 @@ -13,7 +13,6 @@ true - $(DefineConstants);TARGET_BROWSER @@ -32,6 +31,7 @@ + @@ -57,8 +57,7 @@ - - + From 113f9a5aea6a3393d05116ea3cfc782cf3fe0668 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 2 Jun 2026 19:31:51 +0200 Subject: [PATCH 08/11] feedback --- .../vm/eventing/eventpipe/ep-rt-coreclr.h | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 7a215bf18a5e57..bc331427218e0b 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -1047,22 +1047,12 @@ ep_rt_queue_job ( void *params) { #ifdef HOST_BROWSER - // in single-threaded, it will run the callback inline and re-schedule itself if necessary - // it's called from browser event loop - ep_rt_job_cb_t cb = (ep_rt_job_cb_t)job_func; - - // invoke the callback inline for the first time - size_t done = cb (params); - - // see if it's done or needs to be scheduled again - if (!done) { - // self schedule again - SystemJS_DiagnosticServerQueueJob (cb, params); - } - + // 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"); + EP_UNREACHABLE ("Not implemented on this platform"); + return false; #endif } From 805bcdffb61bfbfdca233b58db2fa1f4243417bf Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 2 Jun 2026 19:47:48 +0200 Subject: [PATCH 09/11] feedback --- src/coreclr/vm/gcenv.ee.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 3e0bd1cfb635fc..fbf1085a1a4602 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) { -#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +#if defined(GC_PROFILING) || defined(FEATURE_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,7 @@ void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurr { GCProfileWalkHeap(false); } -#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +#endif // defined(GC_PROFILING) || defined(FEATURE_PERFTRACING_DISABLE_THREADS) #ifdef GC_PROFILING if (CORProfilerTrackBasicGC() || (!fConcurrent && CORProfilerTrackGC())) From dc6f50dde812de387c459eccad188aba525b9558 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 3 Jun 2026 14:42:51 +0200 Subject: [PATCH 10/11] fix V8 spin --- src/native/libs/Common/JavaScript/types/ems-ambient.ts | 2 +- .../libs/System.Native.Browser/diagnostic_server_jobs.c | 6 +++--- .../diagnostics/diagnostic-server-js.ts | 4 ++-- .../diagnostics/diagnostic-server-ws.ts | 4 ++-- .../System.Native.Browser/diagnostics/diagnostic-server.ts | 3 ++- src/native/libs/System.Native.Browser/native/scheduling.ts | 7 +++++-- 6 files changed, 15 insertions(+), 11 deletions(-) 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 { From ed390918aed5a1b7cbe43588d74ce557b6abb762 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 3 Jun 2026 14:59:37 +0200 Subject: [PATCH 11/11] fix --- src/coreclr/vm/gcenv.ee.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index fbf1085a1a4602..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) { -#if defined(GC_PROFILING) || defined(FEATURE_PERFTRACING_DISABLE_THREADS) +#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,7 @@ void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurr { GCProfileWalkHeap(false); } -#endif // defined(GC_PROFILING) || defined(FEATURE_PERFTRACING_DISABLE_THREADS) +#endif // defined(GC_PROFILING) || defined(PERFTRACING_DISABLE_THREADS) #ifdef GC_PROFILING if (CORProfilerTrackBasicGC() || (!fConcurrent && CORProfilerTrackGC()))