diff --git a/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs b/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
new file mode 100644
index 000000000000..dcb69ca07712
--- /dev/null
+++ b/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
@@ -0,0 +1,506 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+#if ES_BUILD_PCL
+ using System.Threading.Tasks;
+#endif
+
+#if MONO
+using System.Diagnostics.Private;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ ///
+ /// Provides the ability to collect statistics through EventSource
+ ///
+ /// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/documentation/EventCounterTutorial.md
+ /// for a tutorial guide.
+ ///
+ /// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs
+ /// which shows tests, which are also useful in seeing actual use.
+ ///
+ public class EventCounter : IDisposable
+ {
+ ///
+ /// Initializes a new instance of the class.
+ /// EVentCounters live as long as the EventSource that they are attached to unless they are
+ /// explicitly Disposed.
+ ///
+ /// The name.
+ /// The event source.
+ public EventCounter(string name, EventSource eventSource)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ if (eventSource == null)
+ {
+ throw new ArgumentNullException(nameof(eventSource));
+ }
+
+ InitializeBuffer();
+ _name = name;
+ _group = EventCounterGroup.GetEventCounterGroup(eventSource);
+ _group.Add(this);
+ _min = float.PositiveInfinity;
+ _max = float.NegativeInfinity;
+ }
+
+ ///
+ /// Writes 'value' to the stream of values tracked by the counter. This updates the sum and other statistics that will
+ /// be logged on the next timer interval.
+ ///
+ /// The value.
+ public void WriteMetric(float value)
+ {
+ Enqueue(value);
+ }
+
+ ///
+ /// Removes the counter from set that the EventSource will report on. After being disposed, this
+ /// counter will do nothing and its resource will be reclaimed if all references to it are removed.
+ /// If an EventCounter is not explicitly disposed it will be cleaned up automatically when the
+ /// EventSource it is attached to dies.
+ ///
+ public void Dispose()
+ {
+ var group = _group;
+ if (group != null)
+ {
+ group.Remove(this);
+ _group = null;
+ }
+ }
+
+ public override string ToString()
+ {
+ return "EventCounter '" + _name + "' Count " + _count + " Mean " + (((double)_sum) / _count).ToString("n3");
+ }
+ #region private implementation
+
+ private readonly string _name;
+ private EventCounterGroup _group;
+
+ #region Buffer Management
+
+ // Values buffering
+ private const int BufferedSize = 10;
+ private const float UnusedBufferSlotValue = float.NegativeInfinity;
+ private const int UnsetIndex = -1;
+ private volatile float[] _bufferedValues;
+ private volatile int _bufferedValuesIndex;
+
+ // arbitrarily we use _bufferfValues as the lock object.
+ private object MyLock { get { return _bufferedValues; } }
+
+ private void InitializeBuffer()
+ {
+ _bufferedValues = new float[BufferedSize];
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ _bufferedValues[i] = UnusedBufferSlotValue;
+ }
+ }
+
+ private void Enqueue(float value)
+ {
+ // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
+ int i = _bufferedValuesIndex;
+ while (true)
+ {
+ float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+ i++;
+ if (_bufferedValues.Length <= i)
+ {
+ // It is possible that two threads both think the buffer is full, but only one get to actually flush it, the other
+ // will eventually enter this code path and potentially calling Flushing on a buffer that is not full, and that's okay too.
+ lock (MyLock) // Lock the counter
+ Flush();
+ i = 0;
+ }
+
+ if (result == UnusedBufferSlotValue)
+ {
+ // CompareExchange succeeded
+ _bufferedValuesIndex = i;
+ return;
+ }
+ }
+ }
+
+ private void Flush()
+ {
+ Debug.Assert(Monitor.IsEntered(MyLock));
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ var value = Interlocked.Exchange(ref _bufferedValues[i], UnusedBufferSlotValue);
+ if (value != UnusedBufferSlotValue)
+ {
+ OnMetricWritten(value);
+ }
+ }
+
+ _bufferedValuesIndex = 0;
+ }
+
+ #endregion // Buffer Management
+
+ #region Statistics Calculation
+
+ // Statistics
+ private int _count;
+ private float _sum;
+ private float _sumSquared;
+ private float _min;
+ private float _max;
+
+ private void OnMetricWritten(float value)
+ {
+ Debug.Assert(Monitor.IsEntered(MyLock));
+ _sum += value;
+ _sumSquared += value * value;
+ if (value > _max)
+ _max = value;
+
+ if (value < _min)
+ _min = value;
+
+ _count++;
+ }
+
+ internal EventCounterPayload GetEventCounterPayload()
+ {
+ lock (MyLock) // Lock the counter
+ {
+ Flush();
+ EventCounterPayload result = new EventCounterPayload();
+ result.Name = _name;
+ result.Count = _count;
+ if (0 < _count)
+ {
+ result.Mean = _sum / _count;
+ result.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+ }
+ else
+ {
+ result.Mean = 0;
+ result.StandardDeviation = 0;
+ }
+ result.Min = _min;
+ result.Max = _max;
+ ResetStatistics();
+ return result;
+ }
+ }
+
+ private void ResetStatistics()
+ {
+ Debug.Assert(Monitor.IsEntered(MyLock));
+ _count = 0;
+ _sum = 0;
+ _sumSquared = 0;
+ _min = float.PositiveInfinity;
+ _max = float.NegativeInfinity;
+ }
+
+ #endregion // Statistics Calculation
+
+ #endregion // private implementation
+ }
+
+ #region internal supporting classes
+
+ [EventData]
+ internal class EventCounterPayload : IEnumerable>
+ {
+ public string Name { get; set; }
+
+ public float Mean { get; set; }
+
+ public float StandardDeviation { get; set; }
+
+ public int Count { get; set; }
+
+ public float Min { get; set; }
+
+ public float Max { get; set; }
+
+ public float IntervalSec { get; internal set; }
+
+ #region Implementation of the IEnumerable interface
+
+ public IEnumerator> GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ private IEnumerable> ForEnumeration
+ {
+ get
+ {
+ yield return new KeyValuePair("Name", Name);
+ yield return new KeyValuePair("Mean", Mean);
+ yield return new KeyValuePair("StandardDeviation", StandardDeviation);
+ yield return new KeyValuePair("Count", Count);
+ yield return new KeyValuePair("Min", Min);
+ yield return new KeyValuePair("Max", Max);
+ }
+ }
+
+ #endregion // Implementation of the IEnumerable interface
+ }
+
+ internal class EventCounterGroup
+ {
+ private readonly EventSource _eventSource;
+ private readonly List _eventCounters;
+
+ internal EventCounterGroup(EventSource eventSource)
+ {
+ _eventSource = eventSource;
+ _eventCounters = new List();
+ RegisterCommandCallback();
+ }
+
+ internal void Add(EventCounter eventCounter)
+ {
+ lock (this) // Lock the EventCounterGroup
+ _eventCounters.Add(eventCounter);
+ }
+
+ internal void Remove(EventCounter eventCounter)
+ {
+ lock (this) // Lock the EventCounterGroup
+ _eventCounters.Remove(eventCounter);
+ }
+
+ #region EventSource Command Processing
+
+ private void RegisterCommandCallback()
+ {
+ // Old destktop runtimes don't have this
+#if NO_EVENTCOMMANDEXECUTED_SUPPORT
+ // We could not build against the API that had the EventCommandExecuted but maybe it is there are runtime.
+ // use reflection to try to get it.
+ System.Reflection.MethodInfo method = typeof(EventSource).GetMethod("add_EventCommandExecuted");
+ if (method != null)
+ {
+ method.Invoke(_eventSource, new object[] { (EventHandler)OnEventSourceCommand });
+ }
+ else
+ {
+ string msg = "EventCounterError: Old Runtime that does not support EventSource.EventCommandExecuted. EventCounters not Supported";
+ _eventSource.Write(msg);
+ Debug.WriteLine(msg);
+ }
+#else
+ _eventSource.EventCommandExecuted += OnEventSourceCommand;
+#endif
+ }
+
+ private void OnEventSourceCommand(object sender, EventCommandEventArgs e)
+ {
+ if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update)
+ {
+ string valueStr;
+ float value;
+ if (e.Arguments.TryGetValue("EventCounterIntervalSec", out valueStr) && float.TryParse(valueStr, out value))
+ {
+ // Recursion through EventSource callbacks possible. When we enable the timer
+ // we synchonously issue a EventSource.Write event, which in turn can call back
+ // to user code (in an EventListener) while holding this lock. This is dangerous
+ // because it mean this code might inadvertantly participate in a lock loop.
+ // The scenario seems very unlikely so we ignore that problem for now.
+ lock (this) // Lock the EventCounterGroup
+ {
+ EnableTimer(value);
+ }
+ }
+ }
+ }
+
+ #endregion // EventSource Command Processing
+
+ #region Global EventCounterGroup Array management
+
+ // We need eventCounters to 'attach' themselves to a particular EventSource.
+ // this table provides the mapping from EventSource -> EventCounterGroup
+ // which represents this 'attached' information.
+ private static WeakReference[] s_eventCounterGroups;
+ private static readonly object s_eventCounterGroupsLock = new object();
+
+ private static void EnsureEventSourceIndexAvailable(int eventSourceIndex)
+ {
+ Debug.Assert(Monitor.IsEntered(s_eventCounterGroupsLock));
+ if (EventCounterGroup.s_eventCounterGroups == null)
+ {
+ EventCounterGroup.s_eventCounterGroups = new WeakReference[eventSourceIndex + 1];
+ }
+ else if (eventSourceIndex >= EventCounterGroup.s_eventCounterGroups.Length)
+ {
+ WeakReference[] newEventCounterGroups = new WeakReference[eventSourceIndex + 1];
+ Array.Copy(EventCounterGroup.s_eventCounterGroups, 0, newEventCounterGroups, 0, EventCounterGroup.s_eventCounterGroups.Length);
+ EventCounterGroup.s_eventCounterGroups = newEventCounterGroups;
+ }
+ }
+
+ internal static EventCounterGroup GetEventCounterGroup(EventSource eventSource)
+ {
+ lock (s_eventCounterGroupsLock)
+ {
+ int eventSourceIndex = EventListenerHelper.EventSourceIndex(eventSource);
+ EnsureEventSourceIndexAvailable(eventSourceIndex);
+ WeakReference weakRef = EventCounterGroup.s_eventCounterGroups[eventSourceIndex];
+ EventCounterGroup ret = null;
+ if (weakRef == null || !weakRef.TryGetTarget(out ret))
+ {
+ ret = new EventCounterGroup(eventSource);
+ EventCounterGroup.s_eventCounterGroups[eventSourceIndex] = new WeakReference(ret);
+ }
+ return ret;
+ }
+ }
+
+ #endregion // Global EventCounterGroup Array management
+
+ #region Timer Processing
+
+ private DateTime _timeStampSinceCollectionStarted;
+ private int _pollingIntervalInMilliseconds;
+ private Timer _pollingTimer;
+
+ private void DisposeTimer()
+ {
+ Debug.Assert(Monitor.IsEntered(this));
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+ }
+
+ private void EnableTimer(float pollingIntervalInSeconds)
+ {
+ Debug.Assert(Monitor.IsEntered(this));
+ if (pollingIntervalInSeconds <= 0)
+ {
+ DisposeTimer();
+ _pollingIntervalInMilliseconds = 0;
+ }
+ else if (_pollingIntervalInMilliseconds == 0 || pollingIntervalInSeconds * 1000 < _pollingIntervalInMilliseconds)
+ {
+ Debug.WriteLine("Polling interval changed at " + DateTime.UtcNow.ToString("mm.ss.ffffff"));
+ _pollingIntervalInMilliseconds = (int)(pollingIntervalInSeconds * 1000);
+ DisposeTimer();
+ _timeStampSinceCollectionStarted = DateTime.UtcNow;
+ _pollingTimer = new Timer(OnTimer, null, _pollingIntervalInMilliseconds, _pollingIntervalInMilliseconds);
+ }
+ // Always fire the timer event (so you see everything up to this time).
+ OnTimer(null);
+ }
+
+ private void OnTimer(object state)
+ {
+ Debug.WriteLine("Timer fired at " + DateTime.UtcNow.ToString("mm.ss.ffffff"));
+ lock (this) // Lock the EventCounterGroup
+ {
+ if (_eventSource.IsEnabled())
+ {
+ DateTime now = DateTime.UtcNow;
+ TimeSpan elapsed = now - _timeStampSinceCollectionStarted;
+
+ foreach (var eventCounter in _eventCounters)
+ {
+ EventCounterPayload payload = eventCounter.GetEventCounterPayload();
+ payload.IntervalSec = (float)elapsed.TotalSeconds;
+ _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PayloadType(payload));
+ }
+ _timeStampSinceCollectionStarted = now;
+ }
+ else
+ {
+ DisposeTimer();
+ }
+ }
+ }
+
+ ///
+ /// This is the payload that is sent in the with EventSource.Write
+ ///
+ [EventData]
+ class PayloadType
+ {
+ public PayloadType(EventCounterPayload payload) { Payload = payload; }
+ public EventCounterPayload Payload { get; set; }
+ }
+
+ #region PCL timer hack
+
+#if ES_BUILD_PCL
+ internal delegate void TimerCallback(object state);
+
+ internal sealed class Timer : CancellationTokenSource, IDisposable
+ {
+ private int _period;
+ private TimerCallback _callback;
+ private object _state;
+
+ internal Timer(TimerCallback callback, object state, int dueTime, int period)
+ {
+ _callback = callback;
+ _state = state;
+ _period = period;
+ Schedule(dueTime);
+ }
+
+ private void Schedule(int dueTime)
+ {
+ Task.Delay(dueTime, Token).ContinueWith(OnTimer, null, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
+ }
+
+ private void OnTimer(Task t, object s)
+ {
+ Schedule(_period);
+ _callback(_state);
+ }
+
+ public new void Dispose() { base.Cancel(); }
+ }
+#endif
+ #endregion // PCL timer hack
+
+ #endregion // Timer Processing
+
+ }
+
+ // This class a work-around because .NET V4.6.2 did not make EventSourceIndex public (it was only protected)
+ // We make this helper class to get around that protection. We want V4.6.3 to make this public at which
+ // point this class is no longer needed and can be removed.
+ internal class EventListenerHelper : EventListener
+ {
+ public new static int EventSourceIndex(EventSource eventSource) { return EventListener.EventSourceIndex(eventSource); }
+ #if MONO
+ internal
+ #endif
+ protected override void OnEventWritten(EventWrittenEventArgs eventData) { } // override abstract methods to keep compiler happy
+ }
+
+ #endregion // internal supporting classes
+}
diff --git a/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/unsafenativemethods.cs b/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/unsafenativemethods.cs
new file mode 100644
index 000000000000..26b6dfddf65e
--- /dev/null
+++ b/external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/unsafenativemethods.cs
@@ -0,0 +1,235 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+/*============================================================
+**
+** Class: UnsafeNativeMethods
+**
+============================================================*/
+namespace Microsoft.Win32 {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Diagnostics.Tracing;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class UnsafeNativeMethods
+ {
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static unsafe class ManifestEtw
+ {
+ //
+ // Constants error coded returned by ETW APIs
+ //
+
+ // The event size is larger than the allowed maximum (64k - header).
+ internal const int ERROR_ARITHMETIC_OVERFLOW = 534;
+
+ // Occurs when filled buffers are trying to flush to disk,
+ // but disk IOs are not happening fast enough.
+ // This happens when the disk is slow and event traffic is heavy.
+ // Eventually, there are no more free (empty) buffers and the event is dropped.
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
+
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_NOT_SUPPORTED = 50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57;
+
+ //
+ // ETW Methods
+ //
+
+ internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
+ internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
+ internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
+
+ //
+ // Callback
+ //
+ [SecurityCritical]
+ internal unsafe delegate void EtwEnableCallback(
+ [In] ref Guid sourceId,
+ [In] int isEnabled,
+ [In] byte level,
+ [In] long matchAnyKeywords,
+ [In] long matchAllKeywords,
+ [In] EVENT_FILTER_DESCRIPTOR* filterData,
+ [In] void* callbackContext
+ );
+
+ //
+ // Registration APIs
+ //
+ [SecurityCritical]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe uint EventRegister(
+ [In] ref Guid providerId,
+ [In]EtwEnableCallback enableCallback,
+ [In]void* callbackContext,
+ [In][Out]ref long registrationHandle
+ );
+
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern uint EventUnregister([In] long registrationHandle);
+
+ //
+ // Writing (Publishing/Logging) APIs
+ //
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWrite", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWrite(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWriteString(
+ [In] long registrationHandle,
+ [In] byte level,
+ [In] long keyword,
+ [In] string msg
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe internal struct EVENT_FILTER_DESCRIPTOR
+ {
+ public long Ptr;
+ public int Size;
+ public int Type;
+ };
+
+ ///
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
+ /// So, for these cases we will retry the call with an empty Guid.
+ ///
+ internal static int EventWriteTransferWrapper(long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ int HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
+ if (HResult == ERROR_INVALID_PARAMETER && relatedActivityId == null)
+ {
+ Guid emptyGuid = Guid.Empty;
+ HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
+ }
+
+ return HResult;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteTransfer", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ private static extern int EventWriteTransfer(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] Guid* activityId,
+ [In] Guid* relatedActivityId,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ internal enum ActivityControl : uint
+ {
+ EVENT_ACTIVITY_CTRL_GET_ID = 1,
+ EVENT_ACTIVITY_CTRL_SET_ID = 2,
+ EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
+ EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
+ EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventActivityIdControl([In] ActivityControl ControlCode, [In][Out] ref Guid ActivityId);
+
+ internal enum EVENT_INFO_CLASS
+ {
+ BinaryTrackInfo,
+ SetEnableAllKeywords,
+ SetTraits,
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventSetInformation", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventSetInformation(
+ [In] long registrationHandle,
+ [In] EVENT_INFO_CLASS informationClass,
+ [In] void* eventInformation,
+ [In] int informationLength);
+
+ // Support for EnumerateTraceGuidsEx
+ internal enum TRACE_QUERY_INFO_CLASS
+ {
+ TraceGuidQueryList,
+ TraceGuidQueryInfo,
+ TraceGuidQueryProcess,
+ TraceStackTracingInfo,
+ MaxTraceSetInfoClass
+ };
+
+ internal struct TRACE_GUID_INFO
+ {
+ public int InstanceCount;
+ public int Reserved;
+ };
+
+ internal struct TRACE_PROVIDER_INSTANCE_INFO
+ {
+ public int NextOffset;
+ public int EnableCount;
+ public int Pid;
+ public int Flags;
+ };
+
+ internal struct TRACE_ENABLE_INFO
+ {
+ public int IsEnabled;
+ public byte Level;
+ public byte Reserved1;
+ public ushort LoggerId;
+ public int EnableProperty;
+ public int Reserved2;
+ public long MatchAnyKeyword;
+ public long MatchAllKeyword;
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EnumerateTraceGuidsEx", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EnumerateTraceGuidsEx(
+ TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
+ void* InBuffer,
+ int InBufferSize,
+ void* OutBuffer,
+ int OutBufferSize,
+ ref int ReturnLength);
+
+ }
+ }
+}
diff --git a/mcs/class/corlib/ReferenceSources/win32native.cs b/mcs/class/corlib/ReferenceSources/win32native.cs
index 06b5c9ea478a..2f27d85c2c69 100644
--- a/mcs/class/corlib/ReferenceSources/win32native.cs
+++ b/mcs/class/corlib/ReferenceSources/win32native.cs
@@ -79,5 +79,8 @@ internal class WIN32_FIND_DATA
internal int dwFileAttributes = 0;
internal String cFileName = null;
}
+
+ [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern uint GetCurrentProcessId();
}
}
\ No newline at end of file
diff --git a/mcs/class/corlib/corlib-net_4_x.csproj b/mcs/class/corlib/corlib-net_4_x.csproj
index f0e0c847d895..0748b480b981 100644
--- a/mcs/class/corlib/corlib-net_4_x.csproj
+++ b/mcs/class/corlib/corlib-net_4_x.csproj
@@ -293,11 +293,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
@@ -980,22 +1016,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources
index bd2fd295fdc5..67203168c076 100644
--- a/mcs/class/corlib/corlib.dll.sources
+++ b/mcs/class/corlib/corlib.dll.sources
@@ -167,22 +167,6 @@ System.Deployment.Internal/InternalApplicationIdentityHelper.cs
System.Diagnostics/Debugger.cs
System.Diagnostics/StackFrame.cs
System.Diagnostics/StackTrace.cs
-System.Diagnostics.Tracing/EventAttribute.cs
-System.Diagnostics.Tracing/EventCommand.cs
-System.Diagnostics.Tracing/EventCounter.cs
-System.Diagnostics.Tracing/EventSource.cs
-System.Diagnostics.Tracing/EventSourceAttribute.cs
-System.Diagnostics.Tracing/EventSourceSettings.cs
-System.Diagnostics.Tracing/EventCommandEventArgs.cs
-System.Diagnostics.Tracing/EventListener.cs
-System.Diagnostics.Tracing/EventWrittenEventArgs.cs
-System.Diagnostics.Tracing/NonEventAttribute.cs
-System.Diagnostics.Tracing/EventDataAttribute.cs
-System.Diagnostics.Tracing/EventFieldAttribute.cs
-System.Diagnostics.Tracing/EventFieldFormat.cs
-System.Diagnostics.Tracing/EventFieldTags.cs
-System.Diagnostics.Tracing/EventIgnoreAttribute.cs
-System.Diagnostics.Tracing/EventManifestOptions.cs
System.Diagnostics.SymbolStore/ISymbolBinder.cs
System.Diagnostics.SymbolStore/ISymbolBinder1.cs
System.Diagnostics.SymbolStore/ISymbolDocument.cs
@@ -1099,12 +1083,49 @@ ReferenceSources/AppContextDefaultValues.cs
../referencesource/mscorlib/system/diagnostics/contracts/contracts.cs
../referencesource/mscorlib/system/diagnostics/contracts/contractsbcl.cs
+../referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs
../referencesource/mscorlib/system/diagnostics/eventing/eventactivityoptions.cs
+../referencesource/mscorlib/system/diagnostics/eventing/eventdescriptor.cs
+../referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs
+../referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs
../referencesource/mscorlib/system/diagnostics/eventing/eventsourceexception.cs
+../referencesource/mscorlib/system/diagnostics/eventing/StubEnvironment.cs
../referencesource/mscorlib/system/diagnostics/eventing/winmeta.cs
+../../../external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
+../../../external/corefx-bugfix/src/Common/src/CoreLib/System/Diagnostics/Tracing/unsafenativemethods.cs
+
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ArrayTypeInfo.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSet.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSetItem.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/DataCollector.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EmptyStruct.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumerableTypeInfo.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumHelper.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventDataAttribute.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldAttribute.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldFormat.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventIgnoreAttribute.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventPayload.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceActivity.cs
../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/FieldMetadata.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/InvokeTypeInfo.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/NameInfo.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAccessor.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAnalysis.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleEventTypes.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/SimpleTypeInfos.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/Statics.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingDataCollector.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingDataType.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventSource.cs
../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventTraits.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingEventTypes.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingMetadataCollector.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingTypeInfo.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TraceLoggingTypeInfo_T.cs
+../referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/TypeAnalysis.cs
../referencesource/mscorlib/system/globalization/bidicategory.cs
../referencesource/mscorlib/system/globalization/calendar.cs
diff --git a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
index 432d81001aa2..79c6bf86ae00 100644
--- a/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
+++ b/mcs/class/referencesource/mscorlib/system/AppContext/AppContextSwitches.cs
@@ -15,6 +15,7 @@ internal static class AppContextSwitches
public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = false;
public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false;
public static readonly bool NoAsyncCurrentCulture = false;
+ public static readonly bool PreserveEventListnerObjectIdentity = false;
#else
private static int _noAsyncCurrentCulture;
public static bool NoAsyncCurrentCulture
diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs
index 22be307d6eea..a77b897e37da 100644
--- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs
+++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/activitytracker.cs
@@ -61,7 +61,7 @@ public void OnStart(string providerName, string activityName, int task, ref Guid
if (m_checkedForEnable)
return;
m_checkedForEnable = true;
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || MONO
Enable(); // Enable it unconditionally.
#else
if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds))
@@ -609,7 +609,7 @@ void ActivityChanging(AsyncLocalValueChangedArgs args)
#endregion
}
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || MONO
/******************************** SUPPORT *****************************/
///
/// This is supplied by the framework. It is has the semantics that the value is copied to any new Tasks that is created
diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs
index 939d15ee520f..54249f1ce6cc 100644
--- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs
+++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventprovider.cs
@@ -78,6 +78,7 @@ internal SessionInfo(int sessionIdBit_, int etwSessionId_)
[SecurityCritical]
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
+ GCHandle m_thisGCHandle;
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
@@ -149,13 +150,25 @@ internal EventProvider()
internal unsafe void Register(Guid providerGuid)
{
m_providerId = providerGuid;
- uint status;
m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
- status = EventRegister(ref m_providerId, m_etwCallback);
- if (status != 0)
+ if (m_thisGCHandle.IsAllocated)
+ m_thisGCHandle.Free();
+
+ m_thisGCHandle = GCHandle.Alloc(this);
+
+ try
+ {
+ var status = UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerGuid, m_etwCallback, GCHandle.ToIntPtr(m_thisGCHandle).ToPointer(), ref m_regHandle);
+ if (status != 0)
+ {
+ throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
+ }
+ }
+ catch
{
- throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
+ m_thisGCHandle.Free();
+ throw;
}
}
@@ -264,22 +277,44 @@ private unsafe void Deregister()
{
EventUnregister();
m_regHandle = 0;
+ m_thisGCHandle.Free();
}
}
+ [AttributeUsage(AttributeTargets.Method)]
+ private sealed class MonoPInvokeCallbackAttribute : Attribute
+ {
+ public MonoPInvokeCallbackAttribute(Type t)
+ {
+ }
+ }
+
+ [MonoPInvokeCallback(typeof(UnsafeNativeMethods.ManifestEtw.EtwEnableCallback))]
+ unsafe static void EtwEnableCallBack(
+ [In] ref System.Guid sourceId,
+ [In] int controlCode,
+ [In] byte setLevel,
+ [In] long anyKeyword,
+ [In] long allKeyword,
+ [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+ [In] void* callbackContext
+ )
+ {
+ var _this = (EventProvider)GCHandle.FromIntPtr(new IntPtr(callbackContext)).Target;
+ _this.EtwEnableCallBackImpl(controlCode, setLevel, anyKeyword, allKeyword, filterData);
+ }
+
//
//
//
//
[System.Security.SecurityCritical]
- unsafe void EtwEnableCallBack(
- [In] ref System.Guid sourceId,
+ unsafe void EtwEnableCallBackImpl(
[In] int controlCode,
[In] byte setLevel,
[In] long anyKeyword,
[In] long allKeyword,
- [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
- [In] void* callbackContext
+ [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData
)
{
// This is an optional callback API. We will therefore ignore any failures that happen as a
@@ -476,9 +511,17 @@ private unsafe void GetSessionInfo(Action action)
fixed (Guid* provider = &m_providerId)
{
- hr = UnsafeNativeMethods.ManifestEtw.EnumerateTraceGuidsEx(UnsafeNativeMethods.ManifestEtw.TRACE_QUERY_INFO_CLASS.TraceGuidQueryInfo,
- provider, sizeof(Guid), buffer, buffSize, ref buffSize);
- }
+ try
+ {
+ hr = UnsafeNativeMethods.ManifestEtw.EnumerateTraceGuidsEx(UnsafeNativeMethods.ManifestEtw.TRACE_QUERY_INFO_CLASS.TraceGuidQueryInfo,
+ provider, sizeof(Guid), buffer, buffSize, ref buffSize);
+ }
+ catch (DllNotFoundException)
+ {
+ // This API isn't available on UWP prior to Windows SDK 16299
+ return;
+ }
+ }
if (hr == 0)
break;
if (hr != 122 /* ERROR_INSUFFICIENT_BUFFER */)
@@ -539,7 +582,7 @@ private unsafe bool GetDataFromController(int etwSessionId,
dataStart = 0;
if (filterData == null)
{
-#if !ES_BUILD_PCL
+#if !ES_BUILD_PCL && !MONO
string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
@@ -1161,13 +1204,6 @@ internal unsafe bool WriteEventRaw(
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
// either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
- [SecurityCritical]
- private unsafe uint EventRegister(ref Guid providerId, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
- {
- m_providerId = providerId;
- m_etwCallback = enableCallback;
- return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
- }
[SecurityCritical]
private uint EventUnregister()
diff --git a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs
index 6bc1f76856fb..b8923813894a 100644
--- a/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs
+++ b/mcs/class/referencesource/mscorlib/system/diagnostics/eventing/eventsource.cs
@@ -200,6 +200,12 @@
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
#endif
+#if MONO
+using TplEtwProvider = System.Diagnostics.Tracing.TplEtwProvider;
+#else
+using TplEtwProvider = System.Threading.Tasks.TplEtwProvider;
+#endif
+
#if ES_BUILD_STANDALONE
namespace Microsoft.Diagnostics.Tracing
#else
@@ -551,8 +557,8 @@ public static void SetCurrentThreadActivityId(Guid activityId)
}
#endif // FEATURE_ACTIVITYSAMPLING
}
- if (System.Threading.Tasks.TplEtwProvider.Log != null)
- System.Threading.Tasks.TplEtwProvider.Log.SetActivityId(activityId);
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
}
///
@@ -586,8 +592,8 @@ public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActiv
// We don't call the activityDying callback here because the caller has declared that
// it is not dying.
- if (System.Threading.Tasks.TplEtwProvider.Log != null)
- System.Threading.Tasks.TplEtwProvider.Log.SetActivityId(activityId);
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
}
///
@@ -4904,7 +4910,7 @@ internal set
}
-#if FEATURE_MANAGED_ETW_CHANNELS
+#if FEATURE_MANAGED_ETW_CHANNELS || MONO
///
/// Gets the channel for the event.
///
@@ -5044,7 +5050,7 @@ internal bool IsOpcodeSet
/// Event's task: allows logical grouping of events
public EventTask Task { get; set; }
-#if FEATURE_MANAGED_ETW_CHANNELS
+#if FEATURE_MANAGED_ETW_CHANNELS || MONO
/// Event's channel: defines an event log as an additional destination for the event
public EventChannel Channel { get; set; }
#endif
@@ -6494,7 +6500,11 @@ private string CreateManifestString()
// very early in the app domain creation, when _FusionStore is not set up yet, resulting in a failure to run the static constructory
// for BinaryCompatibility. This failure is then cached and a TypeInitializationException is thrown every time some code attampts to
// access BinaryCompatibility.
+#if MONO
+ ArraySortHelper.IntrospectiveSort(sortedStrings, 0, sortedStrings.Length, Comparer.Default.Compare);
+#else
ArraySortHelper.IntrospectiveSort(sortedStrings, 0, sortedStrings.Length, Comparer.Default);
+#endif
#endif
foreach (var ci in cultures)
{