Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Portable ThreadPool events to be written using NativeRuntimeEventSource #47829

Merged
merged 34 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
693b36b
match up the GUID
sywhang Jan 20, 2021
99a191d
why is this returning nothing
sywhang Jan 20, 2021
8f71970
Make ThreadPool emit events via NativeRuntimeEventSource
sywhang Jan 20, 2021
2a3d27c
found error...
sywhang Jan 21, 2021
1d53fda
hack around having duplicate events generated
sywhang Jan 21, 2021
8a8ed4a
make portable threadpool fire events through nativeruntimeeventsource
sywhang Jan 21, 2021
ee1869c
make the initializer live in correct namespace
sywhang Jan 22, 2021
16f0841
EventListener tests are passing now
sywhang Jan 22, 2021
e9abcd7
make native QCall endpoints that sink into LTTng
sywhang Jan 28, 2021
d0b4e94
send events through XplatEventLogger sink
sywhang Jan 29, 2021
25c8229
merge with master
sywhang Feb 1, 2021
94052dc
Fix merge error
sywhang Feb 1, 2021
4491a45
double registration
sywhang Feb 1, 2021
d3a16e9
fix callback not getting handled when lttng is enabled
sywhang Feb 3, 2021
82f1d09
cleanup 1
sywhang Feb 3, 2021
03092f6
rename file
sywhang Feb 3, 2021
dc5d82d
remove stale comments
sywhang Feb 3, 2021
9ba77da
remove stale comment
sywhang Feb 3, 2021
3e170b7
undo useless change
sywhang Feb 4, 2021
2da0f68
fix broken EventListener
sywhang Feb 5, 2021
742d0db
apply code review feedback
sywhang Feb 5, 2021
b2d8094
fix windows build
sywhang Feb 5, 2021
fab508d
fix incorrect qcall
sywhang Feb 5, 2021
d239fca
fix up ifdefs for Windows builds
sywhang Feb 5, 2021
e713b67
fix ifdef
sywhang Feb 6, 2021
f94f4de
put back removed code
sywhang Feb 6, 2021
eab8912
tests pass now
sywhang Feb 6, 2021
f89d8af
Fix NativeRuntimeEventSource not getting enabled for lttng
sywhang Feb 8, 2021
7764ec7
Add some more comments
sywhang Feb 8, 2021
31c8e88
Add comment in generated code
sywhang Feb 8, 2021
366f5c7
fix mono build
sywhang Feb 8, 2021
469dfc0
PR feedback
sywhang Feb 10, 2021
070f39a
fix typo
sywhang Feb 10, 2021
283ed56
code review feedback
sywhang Feb 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 15 additions & 25 deletions src/coreclr/scripts/genRuntimeEventSources.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/**********************************************************************

DO NOT MODIFY. AUTOGENERATED FILE.
This file is generated by <root>/src/scripts/genRuntimeEventSources.py
This file is generated by <root>/src/coreclr/scripts/genRuntimeEventSources.py

**********************************************************************/
"""
Expand Down Expand Up @@ -73,22 +73,30 @@ def getCSharpTypeFromManifestType(manifestType):

def generateEvent(eventNode, providerNode, outputFile, stringTable):

# ThreadPool events are defined manually in NativeRuntimeEventSource.PortableThreadPool.cs
symbol = eventNode.getAttribute("symbol")
if "ThreadPool" in symbol:
return

evtLevel = eventNode.getAttribute("level")[4:]
evtKeywords = ""
# Write the event attribute.
writeOutput(outputFile, "[Event("+ eventNode.getAttribute("value") + ", Version = " + eventNode.getAttribute("version") + ", Level = EventLevel." + eventNode.getAttribute("level")[4:])
writeOutput(outputFile, "[Event("+ eventNode.getAttribute("value") + ", Version = " + eventNode.getAttribute("version") + ", Level = EventLevel." + evtLevel)

# Not all events have keywords specified, and some have multiple keywords specified.
keywords = eventNode.getAttribute("keywords")
if keywords:
if " " not in keywords:
outputFile.write(", Keywords = Keywords." + keywords)
evtKeywords = "Keywords." + keywords
else:
keywords = keywords.split()
outputFile.write(", Keywords = ")
for keywordIndex in range(len(keywords)):
outputFile.write("Keywords." + keywords[keywordIndex])
evtKeywords += "Keywords." + keywords[keywordIndex]
if keywordIndex < (len(keywords) - 1):
outputFile.write(" | ")

evtKeywords += " | "
outputFile.write(evtKeywords)
outputFile.write(")]\n")

# Get the template for the event.
Expand Down Expand Up @@ -147,28 +155,10 @@ def generateEvent(eventNode, providerNode, outputFile, stringTable):
outputFile.write(")\n")
writeOutput(outputFile, "{\n")

# Write the call to WriteEvent.
increaseTabLevel()
writeOutput(outputFile, "WriteEvent(" + eventNode.getAttribute("value"))

# Add method parameters.
if argumentCount > 0:
# A ',' is needed after the event id.
outputFile.write(", ")

# Write the parameter names to the method call.
argumentsProcessed = 0
argumentNodes = templateNode.getElementsByTagName("data")
for argumentIndex in range(argumentCount):
argumentNode = argumentNodes[argumentIndex]
argumentName = argumentNode.getAttribute("name")
outputFile.write(argumentName)
if argumentIndex < (argumentCount - 1):
outputFile.write(", ")

outputFile.write(");\n")
writeOutput(outputFile, "// To have this event be emitted from managed side, refer to NativeRuntimeEventSource.cs\n")
writeOutput(outputFile, "throw new NotImplementedException();\n")
decreaseTabLevel()

writeOutput(outputFile, "}\n\n")


Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/corelib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,15 @@
#endif

#if defined(FEATURE_EVENTSOURCE_XPLAT)
#include "nativeeventsource.h"
#include "eventpipeadapter.h"
#include "eventpipeinternal.h"
#include "nativeeventsource.h"
#endif //defined(FEATURE_EVENTSOURCE_XPLAT)

#ifdef FEATURE_PERFTRACING
#include "eventpipeadapter.h"
#include "eventpipeinternal.h"
#include "nativeeventsource.h"
#endif //FEATURE_PERFTRACING

#include "tailcallhelp.h"
Expand Down
19 changes: 16 additions & 3 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -989,12 +989,25 @@ FCFuncStart(gStreamFuncs)
FCFuncEnd()


#if defined(FEATURE_EVENTSOURCE_XPLAT)
#if defined(FEATURE_EVENTSOURCE_XPLAT) || defined(FEATURE_PERFTRACING)
FCFuncStart(gEventLogger)
#if defined(FEATURE_EVENTSOURCE_XPLAT)
QCFuncElement("IsEventSourceLoggingEnabled", XplatEventSourceLogger::IsEventSourceLoggingEnabled)
QCFuncElement("LogEventSource", XplatEventSourceLogger::LogEventSource)
FCFuncEnd()
#endif // defined(FEATURE_EVENTSOURCE_XPLAT)
#if defined(FEATURE_PERFTRACING)
QCFuncElement("LogThreadPoolWorkerThreadStart", NativeEventLogger::LogThreadPoolWorkerThreadStart)
QCFuncElement("LogThreadPoolWorkerThreadStop", NativeEventLogger::LogThreadPoolWorkerThreadStop)
QCFuncElement("LogThreadPoolWorkerThreadWait", NativeEventLogger::LogThreadPoolWorkerThreadWait)
QCFuncElement("LogThreadPoolWorkerThreadAdjustmentSample", NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentSample)
QCFuncElement("LogThreadPoolWorkerThreadAdjustmentAdjustment", NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentAdjustment)
QCFuncElement("LogThreadPoolWorkerThreadAdjustmentStats", NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentStats)
QCFuncElement("LogThreadPoolIOEnqueue", NativeEventLogger::LogThreadPoolIOEnqueue)
QCFuncElement("LogThreadPoolIODequeue", NativeEventLogger::LogThreadPoolIODequeue)
QCFuncElement("LogThreadPoolWorkingThreadCount", NativeEventLogger::LogThreadPoolWorkingThreadCount)
#endif // defined(FEATURE_PERFTRACING)
FCFuncEnd()
#endif // defined(FEATURE_EVENTSOURCE_XPLAT) || defined(FEATURE_PERFTRACING)

#ifdef FEATURE_PERFTRACING
FCFuncStart(gEventPipeInternalFuncs)
Expand Down Expand Up @@ -1200,7 +1213,7 @@ FCClassElement("WeakReference`1", "System", gWeakReferenceOfTFuncs)
FCClassElement("X86Base", "System.Runtime.Intrinsics.X86", gX86BaseFuncs)
#endif // defined(TARGET_X86) || defined(TARGET_AMD64)

#if defined(FEATURE_EVENTSOURCE_XPLAT)
#if defined(FEATURE_EVENTSOURCE_XPLAT) || defined(FEATURE_PERFTRACING)
FCClassElement("XplatEventLogger", "System.Diagnostics.Tracing", gEventLogger)
#endif //defined(FEATURE_EVENTSOURCE_XPLAT)

Expand Down
103 changes: 101 additions & 2 deletions src/coreclr/vm/nativeeventsource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
// ============================================================================

#include "common.h"
#if defined(FEATURE_EVENTSOURCE_XPLAT)
#include "nativeeventsource.h"

#if defined(FEATURE_EVENTSOURCE_XPLAT)

void QCALLTYPE XplatEventSourceLogger::LogEventSource(__in_z int eventID, __in_z LPCWSTR eventName, __in_z LPCWSTR eventSourceName, __in_z LPCWSTR payload)
{
QCALL_CONTRACT;
Expand All @@ -31,7 +32,105 @@ BOOL QCALLTYPE XplatEventSourceLogger::IsEventSourceLoggingEnabled()
END_QCALL;

return retVal;

}

#endif //defined(FEATURE_EVENTSOURCE_XPLAT)

#ifdef FEATURE_PERFTRACING

// These are native QCalls that call into corresponding FireEtw* events for events that want to be emitted from the managed
// side using NativeRuntimeEventSource.
// You need to add them to src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/XplatEventLogger.cs and
// change genRuntimeEventSources.py script to not emit the body that throws NotImplementedException for the event that
// want to be fired from managed code.
// See https://github.com/dotnet/runtime/pull/47829 for an example of how to do this.
void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadStart(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadStart(activeWorkerThreadCount, retiredWorkerThreadCount, clrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadStop(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadStop(activeWorkerThreadCount, retiredWorkerThreadCount, clrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadWait(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadWait(activeWorkerThreadCount, retiredWorkerThreadCount, clrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentSample(__in_z double throughput, __in_z short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadAdjustmentSample(throughput, clrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentAdjustment(__in_z double averageThroughput, __in_z uint newWorkerThreadCount, __in_z uint reason, __in_z short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadAdjustmentAdjustment(averageThroughput, newWorkerThreadCount, reason, clrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkerThreadAdjustmentStats(__in_z double duration, __in_z double throughput, __in_z double threadWave, __in_z double throughputWave, __in_z double throughputErrorEstimate, __in_z double AverageThroughputErrorEstimate, __in_z double ThroughputRatio, __in_z double confidence, __in_z double newControlSetting, __in_z short newThreadWaveMagnitude, __in_z short ClrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkerThreadAdjustmentStats(duration, throughput, threadWave, throughputWave, throughputErrorEstimate, AverageThroughputErrorEstimate, ThroughputRatio, confidence, newControlSetting, newThreadWaveMagnitude, ClrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolIOEnqueue(__in_z void* nativeOverlapped, __in_z void* overlapped, __in_z bool multiDequeues, __in_z short ClrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolIOEnqueue(nativeOverlapped, overlapped, multiDequeues, ClrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolIODequeue(__in_z void* nativeOverlapped, __in_z void* overlapped, __in_z short ClrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolIODequeue(nativeOverlapped, overlapped, ClrInstanceID);

END_QCALL;
}

void QCALLTYPE NativeEventLogger::LogThreadPoolWorkingThreadCount(__in_z uint count, __in_z short ClrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolWorkingThreadCount(count, ClrInstanceID);

END_QCALL;
}
#endif // FEATURE_PERFTRACING
22 changes: 20 additions & 2 deletions src/coreclr/vm/nativeeventsource.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,31 @@
#ifndef _NATIVEEVENTSOURCE_H_
#define _NATIVEEVENTSOURCE_H_

#if defined(FEATURE_EVENTSOURCE_XPLAT)
#include "qcall.h"

#if defined(FEATURE_PERFTRACING)
class XplatEventSourceLogger
{
public:
static void QCALLTYPE LogEventSource(__in_z int eventID, __in_z LPCWSTR eventName, __in_z LPCWSTR eventSourceName, __in_z LPCWSTR payload);
static BOOL QCALLTYPE IsEventSourceLoggingEnabled();
};
#endif //defined(FEATURE_PERFTRACING)

#if defined(FEATURE_PERFTRACING)
class NativeEventLogger
{
public:
static void QCALLTYPE LogThreadPoolWorkerThreadStart(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID);
static void QCALLTYPE LogThreadPoolWorkerThreadStop(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID);
static void QCALLTYPE LogThreadPoolWorkerThreadWait(__in_z uint activeWorkerThreadCount, __in_z uint retiredWorkerThreadCount, __in_z short clrInstanceID);
static void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentSample(__in_z double throughput, __in_z short clrInstanceID);
static void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentAdjustment(__in_z double averageThroughput, __in_z uint newWorkerThreadCount, __in_z uint reason, __in_z short clrInstanceID);
static void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentStats(__in_z double duration, __in_z double throughput, __in_z double threadWave, __in_z double throughputWave, __in_z double throughputErrorEstimate, __in_z double AverageThroughputErrorEstimate, __in_z double ThroughputRatio, __in_z double confidence, __in_z double newControlSetting, __in_z short newThreadWaveMagnitude, __in_z short ClrInstanceID);
static void QCALLTYPE LogThreadPoolIOEnqueue(__in_z void* nativeOverlapped, __in_z void* overlapped, __in_z bool multiDequeues, __in_z short ClrInstanceID);
static void QCALLTYPE LogThreadPoolIODequeue(__in_z void* nativeOverlapped, __in_z void* overlapped, __in_z short ClrInstanceID);
static void QCALLTYPE LogThreadPoolWorkingThreadCount(__in_z uint count, __in_z short ClrInstanceID);
};
#endif // defined(FEATURE_PERFTRACING)

#endif //defined(FEATURE_EVENTSOURCE_XPLAT)
#endif //_NATIVEEVENTSOURCE_H_
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\FieldMetadata.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\InvokeTypeInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\NameInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\NativeEventLogger.cs" Condition="'$(FeaturePerfTracing)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\PropertyAnalysis.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\PropertyValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\SimpleEventTypes.cs" />
Expand All @@ -1222,7 +1223,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\TraceLoggingMetadataCollector.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\TraceLoggingTypeInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\TypeAnalysis.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\XplatEventLogger.cs" Condition="'$(FeatureXplatEventSource)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\TraceLogging\XplatEventLogger.cs" Condition="'$(FeaturePerfTracing)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\QCallHandles.cs" />
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -1949,7 +1950,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadPool.Portable.cs" Condition="'$(FeatureCoreCLR)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadPoolBoundHandle.PlatformNotSupported.cs" Condition="'$(FeatureCoreCLR)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPoolEventSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\NativeRuntimeEventSource.PortableThreadPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.GateThread.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.HillClimbing.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.HillClimbing.Complex.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,18 @@ internal sealed class EventSourceAutoGenerateAttribute : Attribute
/// </remarks>
public partial class EventSource : IDisposable
{
#if FEATURE_EVENTSOURCE_XPLAT
#pragma warning disable CA1823 // field is used to keep listener alive
private static readonly EventListener? persistent_Xplat_Listener = XplatEventLogger.InitializePersistentListener();
#pragma warning restore CA1823
#endif //FEATURE_EVENTSOURCE_XPLAT

internal static bool IsSupported { get; } = InitializeIsSupported();

private static bool InitializeIsSupported() =>
AppContext.TryGetSwitch("System.Diagnostics.Tracing.EventSource.IsSupported", out bool isSupported) ? isSupported : true;

#if FEATURE_EVENTSOURCE_XPLAT
#pragma warning disable CA1823 // field is used to keep listener alive
private static readonly EventListener? persistent_Xplat_Listener = IsSupported ? XplatEventLogger.InitializePersistentListener() : null;
#pragma warning restore CA1823
#endif //FEATURE_EVENTSOURCE_XPLAT

/// <summary>
/// The human-friendly name of the eventSource. It defaults to the simple name of the class
/// </summary>
Expand Down Expand Up @@ -3804,11 +3805,8 @@ public event EventHandler<EventSourceCreatedEventArgs>? EventSourceCreated
static EventListener()
{
#if FEATURE_PERFTRACING
sywhang marked this conversation as resolved.
Show resolved Hide resolved
// Ensure that NativeRuntimeEventSource is initialized so that EventListeners get an opportunity to subscribe to its events.
sywhang marked this conversation as resolved.
Show resolved Hide resolved
// This is required because NativeRuntimeEventSource never emit events on its own, and thus will never be initialized
// in the normal way that EventSources are initialized.
GC.KeepAlive(NativeRuntimeEventSource.Log);
#endif // FEATURE_PERFTRACING
#endif
}

/// <summary>
Expand Down
Loading