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 {