// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // CdsSyncEtwBCLProvider.cs // // [....] // // 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; /// Provides an event source for tracing CDS synchronization information. [System.Runtime.CompilerServices.FriendAccessAllowed] [EventSource( Name = "System.Threading.SynchronizationEventSource", Guid = "EC631D38-466B-4290-9306-834971BA0217", LocalizationResources = "mscorlib")] internal sealed class CdsSyncEtwBCLProvider : EventSource { /// /// Defines the singleton instance for the CDS [....] ETW provider. /// The CDS [....] Event provider GUID is {EC631D38-466B-4290-9306-834971BA0217}. /// public static CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); /// Prevent external instantiation. All logging should go through the Log instance. private CdsSyncEtwBCLProvider() { } /// Enabled for all keywords. 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 }