127 lines
4.7 KiB
C#
127 lines
4.7 KiB
C#
// ==++==
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
//
|
|
// CdsSyncEtwBCLProvider.cs
|
|
//
|
|
// <OWNER>[....]</OWNER>
|
|
//
|
|
// A helper class for firing ETW events related to the Coordination Data Structure
|
|
// [....] primitives. This provider is used by CDS [....] primitives in both mscorlib.dll
|
|
// and system.dll. The purpose of sharing the provider class is to be able to enable
|
|
// ETW tracing on all CDS [....] types with a single ETW provider GUID, and to minimize
|
|
// the number of providers in use.
|
|
//
|
|
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Security;
|
|
|
|
namespace System.Threading
|
|
{
|
|
#if !FEATURE_PAL // PAL doesn't support eventing
|
|
using System.Diagnostics.Tracing;
|
|
|
|
/// <summary>Provides an event source for tracing CDS synchronization information.</summary>
|
|
[System.Runtime.CompilerServices.FriendAccessAllowed]
|
|
[EventSource(
|
|
Name = "System.Threading.SynchronizationEventSource",
|
|
Guid = "EC631D38-466B-4290-9306-834971BA0217",
|
|
LocalizationResources = "mscorlib")]
|
|
internal sealed class CdsSyncEtwBCLProvider : EventSource
|
|
{
|
|
/// <summary>
|
|
/// Defines the singleton instance for the CDS [....] ETW provider.
|
|
/// The CDS [....] Event provider GUID is {EC631D38-466B-4290-9306-834971BA0217}.
|
|
/// </summary>
|
|
public static CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider();
|
|
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
|
|
private CdsSyncEtwBCLProvider() { }
|
|
|
|
/// <summary>Enabled for all keywords.</summary>
|
|
private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);
|
|
|
|
//-----------------------------------------------------------------------------------
|
|
//
|
|
// CDS Synchronization Event IDs (must be unique)
|
|
//
|
|
|
|
private const int SPINLOCK_FASTPATHFAILED_ID = 1;
|
|
private const int SPINWAIT_NEXTSPINWILLYIELD_ID = 2;
|
|
private const int BARRIER_PHASEFINISHED_ID = 3;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SpinLock Events
|
|
//
|
|
|
|
[Event(SPINLOCK_FASTPATHFAILED_ID, Level = EventLevel.Warning)]
|
|
public void SpinLock_FastPathFailed(int ownerID)
|
|
{
|
|
if (IsEnabled(EventLevel.Warning, ALL_KEYWORDS))
|
|
{
|
|
WriteEvent(SPINLOCK_FASTPATHFAILED_ID, ownerID);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SpinWait Events
|
|
//
|
|
|
|
[Event(SPINWAIT_NEXTSPINWILLYIELD_ID, Level = EventLevel.Informational)]
|
|
public void SpinWait_NextSpinWillYield()
|
|
{
|
|
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
|
|
{
|
|
WriteEvent(SPINWAIT_NEXTSPINWILLYIELD_ID);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Events below this point are used by the CDS types in System.dll
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Barrier Events
|
|
//
|
|
|
|
[SecuritySafeCritical]
|
|
[Event(BARRIER_PHASEFINISHED_ID, Level = EventLevel.Verbose, Version=1)]
|
|
public void Barrier_PhaseFinished(bool currentSense, long phaseNum)
|
|
{
|
|
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
|
|
{
|
|
// WriteEvent(BARRIER_PHASEFINISHED_ID, currentSense, phaseNum);
|
|
|
|
// There is no explicit WriteEvent() overload matching this event's bool+long fields.
|
|
// Therefore calling WriteEvent() would hit the "params" overload, which leads to an
|
|
// object allocation every time this event is fired. To prevent that problem we will
|
|
// call WriteEventCore(), which works with a stack based EventData array populated with
|
|
// the event fields.
|
|
unsafe
|
|
{
|
|
EventData* eventPayload = stackalloc EventData[2];
|
|
|
|
Int32 senseAsInt32 = currentSense ? 1 : 0; // write out Boolean as Int32
|
|
eventPayload[0].Size = sizeof(int);
|
|
eventPayload[0].DataPointer = ((IntPtr)(&senseAsInt32));
|
|
eventPayload[1].Size = sizeof(long);
|
|
eventPayload[1].DataPointer = ((IntPtr)(&phaseNum));
|
|
|
|
WriteEventCore(BARRIER_PHASEFINISHED_ID, 2, eventPayload);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif // !FEATURE_PAL
|
|
}
|