diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.CoreCLR.cs index 511476e789fe2..95942b6291c36 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.CoreCLR.cs @@ -97,5 +97,18 @@ private static partial void LogThreadPoolIOPack( IntPtr NativeOverlapped, IntPtr Overlapped, ushort ClrInstanceID); + +#pragma warning disable IDE0060 // Remove unused parameter + [NonEvent] + private static void LogWaitHandleWaitStart( + WaitHandleWaitSourceMap WaitSource, + IntPtr AssociatedObjectID, + ushort ClrInstanceID) => + Debug.Fail("This event is currently not expected to be raised by managed code in CoreCLR."); + + [NonEvent] + private static void LogWaitHandleWaitStop(ushort ClrInstanceID) => + Debug.Fail("This event is currently not expected to be raised by managed code in CoreCLR."); +#pragma warning restore IDE0060 } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs index f25dd2c124f73..1427473092185 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs @@ -11,7 +11,7 @@ public abstract partial class WaitHandle [MethodImpl(MethodImplOptions.InternalCall)] private static extern int WaitOneCore(IntPtr waitHandle, int millisecondsTimeout); - internal static unsafe int WaitMultipleIgnoringSyncContext(Span waitHandles, bool waitAll, int millisecondsTimeout) + private static unsafe int WaitMultipleIgnoringSyncContextCore(Span waitHandles, bool waitAll, int millisecondsTimeout) { fixed (IntPtr* pWaitHandles = &MemoryMarshal.GetReference(waitHandles)) { diff --git a/src/coreclr/gc/env/etmdummy.h b/src/coreclr/gc/env/etmdummy.h index 443e9e21e0941..37e0506374a5e 100644 --- a/src/coreclr/gc/env/etmdummy.h +++ b/src/coreclr/gc/env/etmdummy.h @@ -417,3 +417,5 @@ #define FireEtwAppDomainAssemblyResolveHandlerInvoked(ClrInstanceId, assemblyName, handlerName, resultAssemblyName, resultAssemblyPath) 0 #define FireEtwAssemblyLoadFromResolveHandlerInvoked(ClrInstanceId, assemblyName, isTrackedAssembly, requestingAssemblyPath, requestedAssemblyPath) 0 #define FireEtwEventSource(eventID, eventName, eventSourceName, payload) 0 +#define FireEtwWaitHandleWaitStart(WaitSource, AssociatedObjectID, ClrInstanceID) 0 +#define FireEtwWaitHandleWaitStop(ClrInstanceID) 0 diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index 3648b1f3a7213..3fa3903b05811 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -1153,6 +1153,19 @@ namespace ETW } ContentionFlags; } ContentionStructs; }; + + class WaitHandleLog + { + public: + typedef union _WaitHandleStructs + { + typedef enum _WaitSource { + Unknown=0, + MonitorWait=1 + } WaitSource; + } WaitHandleStructs; + }; + // Class to wrap all Interop logic for ETW class InteropLog { diff --git a/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp b/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp index 6b3e76f6dde1c..17a8010ec1cde 100644 --- a/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp +++ b/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp @@ -84,4 +84,12 @@ EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogExceptionThrown( { } +EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogWaitHandleWaitStart(uint8_t WaitSource, intptr_t AssociatedObjectID, uint16_t ClrInstanceID) +{ +} + +EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogWaitHandleWaitStop(uint16_t ClrInstanceID) +{ +} + #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/gen-eventing-event-inc.lst b/src/coreclr/nativeaot/Runtime/eventpipe/gen-eventing-event-inc.lst index bd8955be9ed59..5abd0e3866926 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/gen-eventing-event-inc.lst +++ b/src/coreclr/nativeaot/Runtime/eventpipe/gen-eventing-event-inc.lst @@ -110,3 +110,5 @@ ThreadPoolWorkerThreadStop ThreadPoolWorkerThreadWait ThreadPoolWorkingThreadCount ThreadRunning +WaitHandleWaitStart +WaitHandleWaitStop diff --git a/src/coreclr/nativeaot/Runtime/runtimeeventinternal.cpp b/src/coreclr/nativeaot/Runtime/runtimeeventinternal.cpp index b346ef52d3351..7b4afafd8671f 100644 --- a/src/coreclr/nativeaot/Runtime/runtimeeventinternal.cpp +++ b/src/coreclr/nativeaot/Runtime/runtimeeventinternal.cpp @@ -100,4 +100,14 @@ EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogExceptionThrown( GetClrInstanceId()); } +EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogWaitHandleWaitStart(uint8_t WaitSource, intptr_t AssociatedObjectID, uint16_t ClrInstanceID) +{ + FireEtwWaitHandleWaitStart(WaitSource, reinterpret_cast(AssociatedObjectID), ClrInstanceID); +} + +EXTERN_C NATIVEAOT_API void __cdecl NativeRuntimeEventSource_LogWaitHandleWaitStop(uint16_t ClrInstanceID) +{ + FireEtwWaitHandleWaitStop(ClrInstanceID); +} + #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.NativeAot.cs index 69e0dbadf06f3..7f214ab0b2bb6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Threading.NativeSinks.NativeAot.cs @@ -22,6 +22,7 @@ public static partial class Keywords public const EventKeywords ContentionKeyword = (EventKeywords)0x4000; public const EventKeywords ThreadingKeyword = (EventKeywords)0x10000; public const EventKeywords ThreadTransferKeyword = (EventKeywords)0x80000000; + public const EventKeywords WaitHandleKeyword = (EventKeywords)0x40000000000; } [NonEvent] @@ -132,5 +133,20 @@ internal static void LogThreadPoolIOPack( { RuntimeImports.NativeRuntimeEventSource_LogThreadPoolIOPack(NativeOverlapped, Overlapped, ClrInstanceID); } + + [NonEvent] + internal static void LogWaitHandleWaitStart( + WaitHandleWaitSourceMap WaitSource, + IntPtr AssociatedObjectID, + ushort ClrInstanceID) + { + RuntimeImports.NativeRuntimeEventSource_LogWaitHandleWaitStart((byte)WaitSource, AssociatedObjectID, ClrInstanceID); + } + + [NonEvent] + internal static void LogWaitHandleWaitStop(ushort ClrInstanceID) + { + RuntimeImports.NativeRuntimeEventSource_LogWaitHandleWaitStop(ClrInstanceID); + } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 733fdece37f1c..33dbf18e3d8d9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -826,6 +826,17 @@ internal static partial void NativeRuntimeEventSource_LogThreadPoolIOPack( [LibraryImport(RuntimeLibrary)] [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] internal static unsafe partial void NativeRuntimeEventSource_LogExceptionThrown(char* exceptionTypeName, char* exceptionMessage, IntPtr faultingIP, long hresult); + + [LibraryImport(RuntimeLibrary)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial void NativeRuntimeEventSource_LogWaitHandleWaitStart( + byte WaitSource, + IntPtr AssociatedObjectID, + ushort ClrInstanceID); + + [LibraryImport(RuntimeLibrary)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static partial void NativeRuntimeEventSource_LogWaitHandleWaitStop(ushort ClrInstanceID); #endif // FEATURE_PERFTRACING // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs index 66636d7f78260..70843a3b940fc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Condition.cs @@ -3,8 +3,8 @@ #pragma warning disable 0420 //passing volatile fields by ref - using System.Diagnostics; +using System.Diagnostics.Tracing; namespace System.Threading { @@ -97,7 +97,7 @@ public Condition(Lock @lock) public bool Wait(TimeSpan timeout) => Wait(WaitHandle.ToTimeoutMilliseconds(timeout)); - public unsafe bool Wait(int millisecondsTimeout) + public unsafe bool Wait(int millisecondsTimeout, object? associatedObjectForMonitorWait = null) { ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1); @@ -111,7 +111,13 @@ public unsafe bool Wait(int millisecondsTimeout) bool success = false; try { - success = waiter.ev.WaitOne(millisecondsTimeout); + success = + waiter.ev.WaitOneNoCheck( + millisecondsTimeout, + associatedObjectForMonitorWait, + associatedObjectForMonitorWait != null + ? NativeRuntimeEventSource.WaitHandleWaitSourceMap.MonitorWait + : NativeRuntimeEventSource.WaitHandleWaitSourceMap.Unknown); } finally { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs index 66016246231fe..c9b270b716dd4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Monitor.NativeAot.cs @@ -146,7 +146,7 @@ public static bool IsEntered(object obj) [UnsupportedOSPlatform("browser")] public static bool Wait(object obj, int millisecondsTimeout) { - return GetCondition(obj).Wait(millisecondsTimeout); + return GetCondition(obj).Wait(millisecondsTimeout, obj); } public static void Pulse(object obj) diff --git a/src/coreclr/scripts/genRuntimeEventSources.py b/src/coreclr/scripts/genRuntimeEventSources.py index f47a30f284519..5fcfbc0476f11 100644 --- a/src/coreclr/scripts/genRuntimeEventSources.py +++ b/src/coreclr/scripts/genRuntimeEventSources.py @@ -85,11 +85,9 @@ def getManifestsToGenerate(runtimeFlavor): def generateEvent(eventNode, providerNode, outputFile, stringTable): - # ThreadPool and Contention events are defined manually in NativeRuntimeEventSource.Threading.cs + # Some threading events are defined manually in NativeRuntimeEventSource.Threading.cs symbol = eventNode.getAttribute("symbol") - if "ThreadPool" in symbol: - return - if "Contention" in symbol: + if any(s in symbol for s in ["ThreadPool", "Contention", "WaitHandle"]): return evtLevel = eventNode.getAttribute("level")[4:] diff --git a/src/coreclr/vm/ClrEtwAll.man b/src/coreclr/vm/ClrEtwAll.man index e04d5b49b1409..265d7a07726cf 100644 --- a/src/coreclr/vm/ClrEtwAll.man +++ b/src/coreclr/vm/ClrEtwAll.man @@ -89,6 +89,8 @@ message="$(string.RuntimePublisher.JitInstrumentationDataKeywordMessage)" symbol="CLR_JITINSTRUMENTEDDATA_KEYWORD" /> + @@ -453,7 +455,13 @@ - + + + + + @@ -504,6 +512,10 @@ + + + + @@ -1775,6 +1787,30 @@ + + + +