summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib
diff options
context:
space:
mode:
authorDavid Mason <davmason@microsoft.com>2019-07-09 22:33:24 -0700
committerGitHub <noreply@github.com>2019-07-09 22:33:24 -0700
commitd61a380bbfde580986f416d8bf3e687104cd5701 (patch)
treed0e68c614ddb138ae2cd01a988df07d6bb22b4cc /src/System.Private.CoreLib
parent27790ab2dbee25d2e9c6fc41863aa7e983552a3f (diff)
downloadcoreclr-d61a380bbfde580986f416d8bf3e687104cd5701.tar.gz
coreclr-d61a380bbfde580986f416d8bf3e687104cd5701.tar.bz2
coreclr-d61a380bbfde580986f416d8bf3e687104cd5701.zip
Let EventPipe threads sleep when no events are available (#25601)
Don't spin forever in EventListener when listening for EventPipe data
Diffstat (limited to 'src/System.Private.CoreLib')
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs9
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs18
2 files changed, 27 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs
index f3f48b4583..b50fdadc8c 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Threading;
#if FEATURE_PERFTRACING
@@ -85,6 +86,11 @@ namespace System.Diagnostics.Tracing
NetTrace
}
+ internal sealed class EventPipeWaitHandle : WaitHandle
+ {
+
+ }
+
internal sealed class EventPipeConfiguration
{
private string m_outputFile;
@@ -251,6 +257,9 @@ namespace System.Diagnostics.Tracing
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
internal static extern unsafe bool GetNextEvent(UInt64 sessionID, EventPipeEventInstanceData* pInstance);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ internal static extern unsafe IntPtr GetWaitHandle(UInt64 sessionID);
}
}
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
index 4360283247..b4ff7d1b08 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Win32.SafeHandles;
namespace System.Diagnostics.Tracing
{
@@ -32,6 +33,7 @@ namespace System.Diagnostics.Tracing
private Int64 m_timeQPCFrequency;
private bool m_stopDispatchTask;
+ private EventPipeWaitHandle m_dispatchTaskWaitHandle = new EventPipeWaitHandle();
private Task? m_dispatchTask = null;
private object m_dispatchControlLock = new object();
private Dictionary<EventListener, EventListenerSubscription> m_subscriptions = new Dictionary<EventListener, EventListenerSubscription>();
@@ -42,6 +44,7 @@ namespace System.Diagnostics.Tracing
{
// Get the ID of the runtime provider so that it can be used as a filter when processing events.
m_RuntimeProviderID = EventPipeInternal.GetProvider(NativeRuntimeEventSource.EventSourceName);
+ m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(IntPtr.Zero, false);
}
internal void SendCommand(EventListener eventListener, EventCommand command, bool enable, EventLevel level, EventKeywords matchAnyKeywords)
@@ -140,6 +143,9 @@ namespace System.Diagnostics.Tracing
if (m_dispatchTask == null)
{
m_stopDispatchTask = false;
+ // Create a SafeWaitHandle that won't release the handle when done
+ m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(EventPipeInternal.GetWaitHandle(m_sessionID), false);
+
m_dispatchTask = Task.Factory.StartNew(DispatchEventsToEventListeners, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
}
@@ -151,6 +157,8 @@ namespace System.Diagnostics.Tracing
if(m_dispatchTask != null)
{
m_stopDispatchTask = true;
+ Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid);
+ Interop.Kernel32.SetEvent(m_dispatchTaskWaitHandle.SafeWaitHandle);
m_dispatchTask.Wait();
m_dispatchTask = null;
}
@@ -163,9 +171,12 @@ namespace System.Diagnostics.Tracing
while (!m_stopDispatchTask)
{
+ bool eventsReceived = false;
// Get the next event.
while (!m_stopDispatchTask && EventPipeInternal.GetNextEvent(m_sessionID, &instanceData))
{
+ eventsReceived = true;
+
// Filter based on provider.
if (instanceData.ProviderID == m_RuntimeProviderID)
{
@@ -179,6 +190,13 @@ namespace System.Diagnostics.Tracing
// Wait for more events.
if (!m_stopDispatchTask)
{
+ if (!eventsReceived)
+ {
+ // Future TODO: this would make more sense to handle in EventPipeSession/EventPipe native code.
+ Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid);
+ m_dispatchTaskWaitHandle.WaitOne();
+ }
+
Thread.Sleep(10);
}
}