You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -61,9 +61,6 @@ namespace System.Threading
|
||||
/// </remarks>
|
||||
public static CancellationToken None
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get { return default(CancellationToken); }
|
||||
}
|
||||
|
||||
@@ -88,9 +85,6 @@ namespace System.Threading
|
||||
/// </remarks>
|
||||
public bool IsCancellationRequested
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
return m_source != null && m_source.IsCancellationRequested;
|
||||
@@ -107,9 +101,6 @@ namespace System.Threading
|
||||
/// </remarks>
|
||||
public bool CanBeCanceled
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
return m_source != null && m_source.CanBeCanceled;
|
||||
@@ -146,9 +137,6 @@ namespace System.Threading
|
||||
/// <summary>
|
||||
/// Internal constructor only a CancellationTokenSource should create a CancellationToken
|
||||
/// </summary>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
internal CancellationToken(CancellationTokenSource source)
|
||||
{
|
||||
m_source = source;
|
||||
@@ -203,8 +191,6 @@ namespace System.Threading
|
||||
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
|
||||
/// be used to deregister the callback.</returns>
|
||||
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
|
||||
/// <exception cref="T:System.ObjectDisposedException">The associated <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
|
||||
public CancellationTokenRegistration Register(Action callback)
|
||||
{
|
||||
if (callback == null)
|
||||
@@ -240,8 +226,6 @@ namespace System.Threading
|
||||
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
|
||||
/// be used to deregister the callback.</returns>
|
||||
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
|
||||
/// <exception cref="T:System.ObjectDisposedException">The associated <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
|
||||
public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext)
|
||||
{
|
||||
if (callback == null)
|
||||
@@ -275,8 +259,6 @@ namespace System.Threading
|
||||
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
|
||||
/// be used to deregister the callback.</returns>
|
||||
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
|
||||
/// <exception cref="T:System.ObjectDisposedException">The associated <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
|
||||
public CancellationTokenRegistration Register(Action<Object> callback, Object state)
|
||||
{
|
||||
if (callback == null)
|
||||
@@ -481,9 +463,6 @@ namespace System.Threading
|
||||
/// <exception cref="System.OperationCanceledException">The token has had cancellation requested.</exception>
|
||||
/// <exception cref="T:System.ObjectDisposedException">The associated <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public void ThrowIfCancellationRequested()
|
||||
{
|
||||
if (IsCancellationRequested)
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace System.Threading
|
||||
/// actually run the callbacks.
|
||||
private volatile int m_threadIDExecutingCallbacks = -1;
|
||||
|
||||
private int m_disposed;
|
||||
private bool m_disposed;
|
||||
|
||||
private CancellationTokenRegistration [] m_linkingRegistrations; //lazily initialized if required.
|
||||
|
||||
@@ -115,9 +115,6 @@ namespace System.Threading
|
||||
/// </remarks>
|
||||
public bool IsCancellationRequested
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get { return m_state >= NOTIFYING; }
|
||||
}
|
||||
|
||||
@@ -134,7 +131,7 @@ namespace System.Threading
|
||||
/// </summary>
|
||||
internal bool IsDisposed
|
||||
{
|
||||
get { return m_disposed == 1; }
|
||||
get { return m_disposed; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,9 +153,6 @@ namespace System.Threading
|
||||
/// disposed.</exception>
|
||||
public CancellationToken Token
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -174,9 +168,6 @@ namespace System.Threading
|
||||
/// </summary>
|
||||
internal bool CanBeCanceled
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get { return m_state != CANNOT_BE_CANCELED; }
|
||||
}
|
||||
|
||||
@@ -260,9 +251,6 @@ namespace System.Threading
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="T:System.Threading.CancellationTokenSource"/>.
|
||||
/// </summary>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public CancellationTokenSource()
|
||||
{
|
||||
m_state = NOT_CANCELED;
|
||||
@@ -572,8 +560,17 @@ namespace System.Threading
|
||||
// This is safe without locks because the reg.Dispose() only
|
||||
// mutates a sparseArrayFragment and then reads from properties of the CTS that are not
|
||||
// invalidated by cts.Dispose().
|
||||
//
|
||||
// We also tolerate that a callback can be registered after the CTS has been
|
||||
// disposed. This is safe without locks because InternalRegister is tolerant
|
||||
// of m_registeredCallbacksLists becoming null during its execution. However,
|
||||
// we run the acceptable risk of m_registeredCallbacksLists getting reinitialized
|
||||
// to non-null if there is a ---- between Dispose and Register, in which case this
|
||||
// instance may unnecessarily hold onto a registered callback. But that's no worse
|
||||
// than if Dispose wasn't safe to use concurrently, as Dispose would never be called,
|
||||
// and thus no handlers would be dropped.
|
||||
|
||||
if (m_disposed != 0 || Interlocked.CompareExchange (ref m_disposed, 1, 0) != 0)
|
||||
if (m_disposed)
|
||||
return;
|
||||
|
||||
if (m_timer != null) m_timer.Dispose();
|
||||
@@ -593,11 +590,35 @@ namespace System.Threading
|
||||
|
||||
m_registeredCallbacksLists = null; // free for GC.
|
||||
|
||||
#if MONO
|
||||
//
|
||||
// .NET version has a race on m_kernelEvent which it's not easy to
|
||||
// trigger on .net probably due to much faster Close implementation
|
||||
// but on Mono this can happen quite easily.
|
||||
//
|
||||
// First race was between Dispose and NotifyCancellation where m_kernelEvent
|
||||
// can be nulled/Closed and Set at same time.
|
||||
//
|
||||
// Second race was between concurrent Dispose calls.
|
||||
//
|
||||
// Third race is between Dispose and WaitHandle propery but that should
|
||||
// be handled by user.
|
||||
//
|
||||
var ke = m_kernelEvent;
|
||||
if (ke != null)
|
||||
{
|
||||
m_kernelEvent = null;
|
||||
ke.Close();
|
||||
}
|
||||
#else
|
||||
if (m_kernelEvent != null)
|
||||
{
|
||||
m_kernelEvent.Close(); // the critical cleanup to release an OS handle
|
||||
m_kernelEvent = null; // free for GC.
|
||||
}
|
||||
#endif
|
||||
|
||||
m_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,12 +627,9 @@ namespace System.Threading
|
||||
/// <summary>
|
||||
/// Throws an exception if the source has been disposed.
|
||||
/// </summary>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
internal void ThrowIfDisposed()
|
||||
{
|
||||
if (m_disposed == 1)
|
||||
if (m_disposed)
|
||||
ThrowObjectDisposedException();
|
||||
}
|
||||
|
||||
@@ -638,7 +656,10 @@ namespace System.Threading
|
||||
internal CancellationTokenRegistration InternalRegister(
|
||||
Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
}
|
||||
|
||||
// the CancellationToken has already checked that the token is cancelable before calling this method.
|
||||
Contract.Assert(CanBeCanceled, "Cannot register for uncancelable token src");
|
||||
@@ -650,6 +671,20 @@ namespace System.Threading
|
||||
|
||||
if (!IsCancellationRequested)
|
||||
{
|
||||
// In order to enable code to not leak too many handlers, we allow Dispose to be called concurrently
|
||||
// with Register. While this is not a recommended practice, consumers can and do use it this way.
|
||||
// We don't make any guarantees about whether the CTS will hold onto the supplied callback
|
||||
// if the CTS has already been disposed when the callback is registered, but we try not to
|
||||
// while at the same time not paying any non-negligible overhead. The simple compromise
|
||||
// is to check whether we're disposed (not volatile), and if we see we are, to return an empty
|
||||
// registration, just as if CanBeCanceled was false for the check made in CancellationToken.Register.
|
||||
// If there's a ---- and m_disposed is false even though it's been disposed, or if the disposal request
|
||||
// comes in after this line, we simply run the minor risk of having m_registeredCallbacksLists reinitialized
|
||||
// (after it was cleared to null during Dispose).
|
||||
|
||||
if (m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
|
||||
return new CancellationTokenRegistration();
|
||||
|
||||
int myIndex = Thread.CurrentThread.ManagedThreadId % s_nLists;
|
||||
|
||||
CancellationCallbackInfo callbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
|
||||
@@ -717,8 +752,23 @@ namespace System.Threading
|
||||
ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
|
||||
|
||||
//If the kernel event is null at this point, it will be set during lazy construction.
|
||||
#if MONO
|
||||
var ke = m_kernelEvent;
|
||||
if (ke != null) {
|
||||
try {
|
||||
ke.Set(); // update the MRE value.
|
||||
} catch (ObjectDisposedException) {
|
||||
//
|
||||
// Rethrow only when we are not in race with Dispose
|
||||
//
|
||||
if (m_kernelEvent != null)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (m_kernelEvent != null)
|
||||
m_kernelEvent.Set(); // update the MRE value.
|
||||
#endif
|
||||
|
||||
// - late enlisters to the Canceled event will have their callbacks called immediately in the Register() methods.
|
||||
// - Callbacks are not called inside a lock.
|
||||
@@ -858,9 +908,6 @@ namespace System.Threading
|
||||
/// <param name="token2">The second <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to observe.</param>
|
||||
/// <returns>A <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that is linked
|
||||
/// to the source tokens.</returns>
|
||||
/// <exception cref="T:System.ObjectDisposedException">A <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with
|
||||
/// one of the source tokens has been disposed.</exception>
|
||||
public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
|
||||
{
|
||||
CancellationTokenSource linkedTokenSource = new CancellationTokenSource();
|
||||
@@ -895,9 +942,6 @@ namespace System.Threading
|
||||
/// <returns>A <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that is linked
|
||||
/// to the source tokens.</returns>
|
||||
/// <exception cref="T:System.ArgumentNullException"><paramref name="tokens"/> is null.</exception>
|
||||
/// <exception cref="T:System.ObjectDisposedException">A <see
|
||||
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with
|
||||
/// one of the source tokens has been disposed.</exception>
|
||||
public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens)
|
||||
{
|
||||
if (tokens == null)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
@@ -8,14 +7,23 @@
|
||||
// <OWNER>AlfreMen</OWNER>
|
||||
//
|
||||
|
||||
#if MONO
|
||||
#undef FEATURE_COMINTEROP
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#if FEATURE_COMINTEROP
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
|
||||
using WFD = Windows.Foundation.Diagnostics;
|
||||
#endif
|
||||
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
@@ -23,39 +31,91 @@ namespace System.Threading.Tasks
|
||||
[FriendAccessAllowed]
|
||||
internal enum CausalityTraceLevel
|
||||
{
|
||||
#if FEATURE_COMINTEROP
|
||||
Required = WFD.CausalityTraceLevel.Required,
|
||||
Important = WFD.CausalityTraceLevel.Important,
|
||||
Verbose = WFD.CausalityTraceLevel.Verbose
|
||||
#else
|
||||
Required,
|
||||
Important,
|
||||
Verbose
|
||||
#endif
|
||||
}
|
||||
|
||||
[FriendAccessAllowed]
|
||||
internal enum AsyncCausalityStatus
|
||||
{
|
||||
#if FEATURE_COMINTEROP
|
||||
Canceled = WFD.AsyncCausalityStatus.Canceled,
|
||||
Completed = WFD.AsyncCausalityStatus.Completed,
|
||||
Error = WFD.AsyncCausalityStatus.Error,
|
||||
Started = WFD.AsyncCausalityStatus.Started
|
||||
#else
|
||||
Started,
|
||||
Completed,
|
||||
Canceled,
|
||||
Error
|
||||
#endif
|
||||
}
|
||||
|
||||
internal enum CausalityRelation
|
||||
{
|
||||
#if FEATURE_COMINTEROP
|
||||
AssignDelegate = WFD.CausalityRelation.AssignDelegate,
|
||||
Join = WFD.CausalityRelation.Join,
|
||||
Choice = WFD.CausalityRelation.Choice,
|
||||
Cancel = WFD.CausalityRelation.Cancel,
|
||||
Error = WFD.CausalityRelation.Error
|
||||
#else
|
||||
AssignDelegate,
|
||||
Join,
|
||||
Choice,
|
||||
Cancel,
|
||||
Error
|
||||
#endif
|
||||
}
|
||||
|
||||
internal enum CausalitySynchronousWork
|
||||
{
|
||||
#if FEATURE_COMINTEROP
|
||||
CompletionNotification = WFD.CausalitySynchronousWork.CompletionNotification,
|
||||
ProgressNotification = WFD.CausalitySynchronousWork.ProgressNotification,
|
||||
Execution = WFD.CausalitySynchronousWork.Execution
|
||||
#else
|
||||
CompletionNotification,
|
||||
ProgressNotification,
|
||||
Execution
|
||||
#endif
|
||||
}
|
||||
|
||||
[FriendAccessAllowed]
|
||||
internal static class AsyncCausalityTracer
|
||||
{
|
||||
static internal void EnableToETW(bool enabled)
|
||||
{
|
||||
#if !MONO
|
||||
if (enabled)
|
||||
f_LoggingOn |= Loggers.ETW;
|
||||
else
|
||||
f_LoggingOn &= ~Loggers.ETW;
|
||||
#endif
|
||||
}
|
||||
|
||||
[FriendAccessAllowed]
|
||||
internal static bool LoggingOn
|
||||
{
|
||||
[FriendAccessAllowed]
|
||||
get
|
||||
{
|
||||
#if FEATURE_COMINTEROP
|
||||
return f_LoggingOn != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if FEATURE_COMINTEROP
|
||||
//s_PlatformId = {4B0171A6-F3D0-41A0-9B33-02550652B995}
|
||||
private static readonly Guid s_PlatformId = new Guid(0x4B0171A6, 0xF3D0, 0x41A0, 0x9B, 0x33, 0x02, 0x55, 0x06, 0x52, 0xB9, 0x95);
|
||||
|
||||
@@ -65,33 +125,23 @@ namespace System.Threading.Tasks
|
||||
//Lazy initialize the actual factory
|
||||
private static WFD.IAsyncCausalityTracerStatics s_TracerFactory;
|
||||
|
||||
//We receive the actual value for these as a callback
|
||||
private static bool f_LoggingOn; //assumes false by default
|
||||
|
||||
[FriendAccessAllowed]
|
||||
internal static bool LoggingOn
|
||||
{
|
||||
[FriendAccessAllowed]
|
||||
get
|
||||
{
|
||||
if (!f_FactoryInitialized)
|
||||
FactoryInitialized();
|
||||
|
||||
return f_LoggingOn;
|
||||
}
|
||||
// The loggers that this Tracer knows about.
|
||||
[Flags]
|
||||
private enum Loggers : byte {
|
||||
CausalityTracer = 1,
|
||||
ETW = 2
|
||||
}
|
||||
|
||||
private static bool f_FactoryInitialized; //assumes false by default
|
||||
private static object _InitializationLock = new object();
|
||||
|
||||
//explicit cache
|
||||
private static readonly Func<WFD.IAsyncCausalityTracerStatics> s_loadFactoryDelegate = LoadFactory;
|
||||
//We receive the actual value for these as a callback
|
||||
private static Loggers f_LoggingOn; //assumes false by default
|
||||
|
||||
// The precise static constructor will run first time somebody attempts to access this class
|
||||
[SecuritySafeCritical]
|
||||
private static WFD.IAsyncCausalityTracerStatics LoadFactory()
|
||||
static AsyncCausalityTracer()
|
||||
{
|
||||
if (!Environment.IsWinRTSupported) return null;
|
||||
|
||||
if (!Environment.IsWinRTSupported) return;
|
||||
|
||||
//COM Class Id
|
||||
string ClassId = "Windows.Foundation.Diagnostics.AsyncCausalityTracer";
|
||||
|
||||
@@ -99,84 +149,149 @@ namespace System.Threading.Tasks
|
||||
Guid guid = new Guid(0x50850B26, 0x267E, 0x451B, 0xA8, 0x90, 0XAB, 0x6A, 0x37, 0x02, 0x45, 0xEE);
|
||||
|
||||
Object factory = null;
|
||||
|
||||
WFD.IAsyncCausalityTracerStatics validFactory = null;
|
||||
|
||||
try
|
||||
{
|
||||
int hresult = Microsoft.Win32.UnsafeNativeMethods.RoGetActivationFactory(ClassId, ref guid, out factory);
|
||||
|
||||
if (hresult < 0 || factory == null) return null; //This prevents having an exception thrown in case IAsyncCausalityTracerStatics isn't registered.
|
||||
if (hresult < 0 || factory == null) return; //This prevents having an exception thrown in case IAsyncCausalityTracerStatics isn't registered.
|
||||
|
||||
validFactory = (WFD.IAsyncCausalityTracerStatics)factory;
|
||||
s_TracerFactory = (WFD.IAsyncCausalityTracerStatics)factory;
|
||||
|
||||
EventRegistrationToken token = validFactory.add_TracingStatusChanged(new EventHandler<WFD.TracingStatusChangedEventArgs>(TracingStatusChangedHandler));
|
||||
Contract.Assert(token != null, "EventRegistrationToken is null");
|
||||
EventRegistrationToken token = s_TracerFactory.add_TracingStatusChanged(new EventHandler<WFD.TracingStatusChangedEventArgs>(TracingStatusChangedHandler));
|
||||
Contract.Assert(token != default(EventRegistrationToken), "EventRegistrationToken is null");
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Although catching generic Exception is not recommended, this file is one exception
|
||||
// since we don't want to propagate any kind of exception to the user since all we are
|
||||
// doing here depends on internal state.
|
||||
return null;
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
|
||||
return validFactory;
|
||||
}
|
||||
|
||||
private static bool FactoryInitialized()
|
||||
{
|
||||
return (LazyInitializer.EnsureInitialized(ref s_TracerFactory, ref f_FactoryInitialized, ref _InitializationLock, s_loadFactoryDelegate) != null);
|
||||
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private static void TracingStatusChangedHandler(Object sender, WFD.TracingStatusChangedEventArgs args)
|
||||
{
|
||||
f_LoggingOn = args.Enabled;
|
||||
if (args.Enabled)
|
||||
f_LoggingOn |= Loggers.CausalityTracer;
|
||||
else
|
||||
f_LoggingOn &= ~Loggers.CausalityTracer;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// The TraceXXX methods should be called only if LoggingOn property returned true
|
||||
//
|
||||
|
||||
[FriendAccessAllowed]
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Tracking is slow path. Disable inlining for it.
|
||||
internal static void TraceOperationCreation(CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext)
|
||||
{
|
||||
if (LoggingOn)
|
||||
#if FEATURE_COMINTEROP
|
||||
try
|
||||
{
|
||||
s_TracerFactory.TraceOperationCreation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), operationName, relatedContext);
|
||||
if ((f_LoggingOn & Loggers.ETW) != 0)
|
||||
TplEtwProvider.Log.TraceOperationBegin(taskId, operationName, (long) relatedContext);
|
||||
if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
|
||||
s_TracerFactory.TraceOperationCreation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), operationName, relatedContext);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//view function comment
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[FriendAccessAllowed]
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
internal static void TraceOperationCompletion(CausalityTraceLevel traceLevel, int taskId, AsyncCausalityStatus status)
|
||||
{
|
||||
if (LoggingOn)
|
||||
#if FEATURE_COMINTEROP
|
||||
try
|
||||
{
|
||||
s_TracerFactory.TraceOperationCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.AsyncCausalityStatus)status);
|
||||
if ((f_LoggingOn & Loggers.ETW) != 0)
|
||||
TplEtwProvider.Log.TraceOperationEnd(taskId, status);
|
||||
if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
|
||||
s_TracerFactory.TraceOperationCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.AsyncCausalityStatus)status);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//view function comment
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
internal static void TraceOperationRelation(CausalityTraceLevel traceLevel, int taskId, CausalityRelation relation)
|
||||
{
|
||||
if (LoggingOn)
|
||||
#if FEATURE_COMINTEROP
|
||||
try
|
||||
{
|
||||
s_TracerFactory.TraceOperationRelation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalityRelation)relation);
|
||||
if ((f_LoggingOn & Loggers.ETW) != 0)
|
||||
TplEtwProvider.Log.TraceOperationRelation(taskId, relation);
|
||||
if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
|
||||
s_TracerFactory.TraceOperationRelation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalityRelation)relation);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//view function comment
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
internal static void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, int taskId, CausalitySynchronousWork work)
|
||||
{
|
||||
if (LoggingOn)
|
||||
#if FEATURE_COMINTEROP
|
||||
try
|
||||
{
|
||||
s_TracerFactory.TraceSynchronousWorkStart((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalitySynchronousWork)work);
|
||||
if ((f_LoggingOn & Loggers.ETW) != 0)
|
||||
TplEtwProvider.Log.TraceSynchronousWorkBegin(taskId, work);
|
||||
if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
|
||||
s_TracerFactory.TraceSynchronousWorkStart((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalitySynchronousWork)work);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//view function comment
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
internal static void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySynchronousWork work)
|
||||
{
|
||||
if (LoggingOn)
|
||||
#if FEATURE_COMINTEROP
|
||||
try
|
||||
{
|
||||
s_TracerFactory.TraceSynchronousWorkCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, (WFD.CausalitySynchronousWork)work);
|
||||
if ((f_LoggingOn & Loggers.ETW) != 0)
|
||||
TplEtwProvider.Log.TraceSynchronousWorkEnd(work);
|
||||
if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
|
||||
s_TracerFactory.TraceSynchronousWorkCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, (WFD.CausalitySynchronousWork)work);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//view function comment
|
||||
LogAndDisable(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if FEATURE_COMINTEROP
|
||||
//fix for 796185: leaking internal exceptions to customers,
|
||||
//we should catch and log exceptions but never propagate them.
|
||||
private static void LogAndDisable(Exception ex)
|
||||
{
|
||||
f_LoggingOn = 0;
|
||||
Debugger.Log(0, "AsyncCausalityTracer", ex.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
private static ulong GetOperationId(uint taskId)
|
||||
{
|
||||
return (((ulong)AppDomain.CurrentDomain.Id) << 32) + taskId;
|
||||
@@ -184,5 +299,3 @@ namespace System.Threading.Tasks
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -529,9 +529,6 @@ namespace System.Threading.Tasks
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
public TResult Result
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get { return IsWaitNotificationEnabledOrNotRanToCompletion ? GetResultCore(waitCompletionNotification: true) : m_result; }
|
||||
}
|
||||
|
||||
@@ -544,9 +541,6 @@ namespace System.Threading.Tasks
|
||||
/// </remarks>
|
||||
internal TResult ResultOnSuccess
|
||||
{
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
get
|
||||
{
|
||||
Contract.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion,
|
||||
@@ -695,15 +689,11 @@ namespace System.Threading.Tasks
|
||||
Contract.Assert(false, "Invalid m_action in Task<TResult>");
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
#region Await Support
|
||||
|
||||
/// <summary>Gets an awaiter used to await this <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
|
||||
/// <returns>An awaiter instance.</returns>
|
||||
/// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public new TaskAwaiter<TResult> GetAwaiter()
|
||||
{
|
||||
return new TaskAwaiter<TResult>(this);
|
||||
@@ -714,16 +704,13 @@ namespace System.Threading.Tasks
|
||||
/// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
|
||||
/// </param>
|
||||
/// <returns>An object used to await this task.</returns>
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public new ConfiguredTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext)
|
||||
{
|
||||
return new ConfiguredTaskAwaitable<TResult>(this, continueOnCapturedContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#region Continuation methods
|
||||
|
||||
#region Action<Task<TResult>> continuations
|
||||
|
||||
@@ -1 +1 @@
|
||||
f17b2462e4086665f52411414a2a86cc9103e256
|
||||
4168909f0dd17449e19e6aed3039bce3e82ce073
|
||||
@@ -1 +1 @@
|
||||
612ac932e336859218839634e39d03f00ec318de
|
||||
2b64b423d8e28a317807644569681db96f0c3521
|
||||
@@ -18,10 +18,10 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
#if !FEATURE_PAL // PAL doesn't support eventing
|
||||
using System.Diagnostics.Tracing;
|
||||
|
||||
/// <summary>Provides an event source for tracing TPL information.</summary>
|
||||
@@ -31,6 +31,31 @@ namespace System.Threading.Tasks
|
||||
LocalizationResources = "mscorlib")]
|
||||
internal sealed class TplEtwProvider : EventSource
|
||||
{
|
||||
/// Used to determine if tasks should generate Activity IDs for themselves
|
||||
internal bool TasksSetActivityIds; // This keyword is set
|
||||
internal bool Debug;
|
||||
private bool DebugActivityId;
|
||||
|
||||
/// <summary>
|
||||
/// Get callbacks when the ETW sends us commands`
|
||||
/// </summary>
|
||||
protected override void OnEventCommand(EventCommandEventArgs command)
|
||||
{
|
||||
// To get the AsyncCausality events, we need to inform the AsyncCausalityTracer
|
||||
if (command.Command == EventCommand.Enable)
|
||||
AsyncCausalityTracer.EnableToETW(true);
|
||||
else if (command.Command == EventCommand.Disable)
|
||||
AsyncCausalityTracer.EnableToETW(false);
|
||||
|
||||
if (IsEnabled(EventLevel.Informational, Keywords.TasksFlowActivityIds))
|
||||
ActivityTracker.Instance.Enable();
|
||||
else
|
||||
TasksSetActivityIds = IsEnabled(EventLevel.Informational, Keywords.TasksSetActivityIds);
|
||||
|
||||
Debug = IsEnabled(EventLevel.Informational, Keywords.Debug);
|
||||
DebugActivityId = IsEnabled(EventLevel.Informational, Keywords.DebugActivityId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the singleton instance for the TPL ETW provider.
|
||||
/// The TPL Event provider GUID is {2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5}.
|
||||
@@ -76,6 +101,10 @@ namespace System.Threading.Tasks
|
||||
public const EventTask TaskScheduled = (EventTask)6;
|
||||
/// <summary>An await task continuation is scheduled to execute.</summary>
|
||||
public const EventTask AwaitTaskContinuationScheduled = (EventTask)7;
|
||||
|
||||
/// <summary>AsyncCausalityFunctionality.</summary>
|
||||
public const EventTask TraceOperation = (EventTask)8;
|
||||
public const EventTask TraceSynchronousWork = (EventTask)9;
|
||||
}
|
||||
|
||||
public class Keywords // thisname is important for EventSource
|
||||
@@ -94,6 +123,40 @@ namespace System.Threading.Tasks
|
||||
/// Events associted with the higher level parallel APIs
|
||||
/// </summary>
|
||||
public const EventKeywords Parallel = (EventKeywords) 4;
|
||||
/// <summary>
|
||||
/// These are relatively verbose events that effectively just redirect
|
||||
/// the windows AsyncCausalityTracer to ETW
|
||||
/// </summary>
|
||||
public const EventKeywords AsyncCausalityOperation = (EventKeywords) 8;
|
||||
public const EventKeywords AsyncCausalityRelation = (EventKeywords) 0x10;
|
||||
public const EventKeywords AsyncCausalitySynchronousWork = (EventKeywords) 0x20;
|
||||
|
||||
/// <summary>
|
||||
/// Emit the stops as well as the schedule/start events
|
||||
/// </summary>
|
||||
public const EventKeywords TaskStops = (EventKeywords) 0x40;
|
||||
|
||||
/// <summary>
|
||||
/// TasksFlowActivityIds indicate that activity ID flow from one task
|
||||
/// to any task created by it.
|
||||
/// </summary>
|
||||
public const EventKeywords TasksFlowActivityIds = (EventKeywords) 0x80;
|
||||
|
||||
/// <summary>
|
||||
/// TasksSetActivityIds will cause the task operations to set Activity Ids
|
||||
/// This option is incompatible with TasksFlowActivityIds flow is ignored
|
||||
/// if that keyword is set. This option is likley to be removed in the future
|
||||
/// </summary>
|
||||
public const EventKeywords TasksSetActivityIds = (EventKeywords) 0x10000;
|
||||
|
||||
/// <summary>
|
||||
/// Relatively Verbose logging meant for debugging the Task library itself. Will probably be removed in the future
|
||||
/// </summary>
|
||||
public const EventKeywords Debug = (EventKeywords) 0x20000;
|
||||
/// <summary>
|
||||
/// Relatively Verbose logging meant for debugging the Task library itself. Will probably be removed in the future
|
||||
/// </summary>
|
||||
public const EventKeywords DebugActivityId = (EventKeywords) 0x40000;
|
||||
}
|
||||
|
||||
/// <summary>Enabled for all keywords.</summary>
|
||||
@@ -129,6 +192,18 @@ namespace System.Threading.Tasks
|
||||
private const int TASKWAITEND_ID = 11;
|
||||
/// <summary>A continuation of a task is scheduled.</summary>
|
||||
private const int AWAITTASKCONTINUATIONSCHEDULED_ID = 12;
|
||||
/// <summary>A continuation of a taskWaitEnd is complete </summary>
|
||||
private const int TASKWAITCONTINUATIONCOMPLETE_ID = 13;
|
||||
/// <summary>A continuation of a taskWaitEnd is complete </summary>
|
||||
private const int TASKWAITCONTINUATIONSTARTED_ID = 19;
|
||||
|
||||
private const int TRACEOPERATIONSTART_ID = 14;
|
||||
private const int TRACEOPERATIONSTOP_ID = 15;
|
||||
private const int TRACEOPERATIONRELATION_ID = 16;
|
||||
private const int TRACESYNCHRONOUSWORKSTART_ID = 17;
|
||||
private const int TRACESYNCHRONOUSWORKSTOP_ID = 18;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//
|
||||
// Parallel Events
|
||||
@@ -145,7 +220,8 @@ namespace System.Threading.Tasks
|
||||
/// <param name="InclusiveFrom">The lower bound of the loop.</param>
|
||||
/// <param name="ExclusiveTo">The upper bound of the loop.</param>
|
||||
[SecuritySafeCritical]
|
||||
[Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)]
|
||||
[Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
|
||||
Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)]
|
||||
public void ParallelLoopBegin(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
|
||||
@@ -226,7 +302,8 @@ namespace System.Threading.Tasks
|
||||
/// <param name="OperationType">The kind of fork/join operation.</param>
|
||||
/// <param name="ActionCount">The number of actions being invoked.</param>
|
||||
[SecuritySafeCritical]
|
||||
[Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)]
|
||||
[Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
|
||||
Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)]
|
||||
public void ParallelInvokeBegin(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
|
||||
@@ -286,7 +363,8 @@ namespace System.Threading.Tasks
|
||||
/// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="ForkJoinContextID">The invoke ID.</param>
|
||||
[Event(PARALLELFORK_ID, Level = EventLevel.Verbose, Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
|
||||
[Event(PARALLELFORK_ID, Level = EventLevel.Verbose, ActivityOptions=EventActivityOptions.Recursive,
|
||||
Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
|
||||
public void ParallelFork(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int ForkJoinContextID)
|
||||
@@ -338,11 +416,11 @@ namespace System.Threading.Tasks
|
||||
/// <param name="CreatingTaskID">The task ID</param>
|
||||
/// <param name="TaskCreationOptions">The options used to create the task.</param>
|
||||
[SecuritySafeCritical]
|
||||
[Event(TASKSCHEDULED_ID, Task = Tasks.TaskScheduled, Opcode = EventOpcode.Send,
|
||||
[Event(TASKSCHEDULED_ID, Task = Tasks.TaskScheduled, Version=1, Opcode = EventOpcode.Send,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
|
||||
public void TaskScheduled(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int TaskID, int CreatingTaskID, int TaskCreationOptions)
|
||||
int TaskID, int CreatingTaskID, int TaskCreationOptions, int appDomain)
|
||||
{
|
||||
// IsEnabled() call is an inlined quick check that makes this very fast when provider is off
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
|
||||
@@ -360,8 +438,13 @@ namespace System.Threading.Tasks
|
||||
eventPayload[3].DataPointer = ((IntPtr) (&CreatingTaskID));
|
||||
eventPayload[4].Size = sizeof(int);
|
||||
eventPayload[4].DataPointer = ((IntPtr) (&TaskCreationOptions));
|
||||
Guid childActivityId = CreateGuidForTaskID(TaskID);
|
||||
WriteEventWithRelatedActivityIdCore(TASKSCHEDULED_ID, &childActivityId, 5, eventPayload);
|
||||
if (TasksSetActivityIds)
|
||||
{
|
||||
Guid childActivityId = CreateGuidForTaskID(TaskID);
|
||||
WriteEventWithRelatedActivityIdCore(TASKSCHEDULED_ID, &childActivityId, 5, eventPayload);
|
||||
}
|
||||
else
|
||||
WriteEventCore(TASKSCHEDULED_ID, 5, eventPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,7 +457,7 @@ namespace System.Threading.Tasks
|
||||
/// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
[Event(TASKSTARTED_ID, Task = TplEtwProvider.Tasks.TaskExecute, Opcode = EventOpcode.Start,
|
||||
[Event(TASKSTARTED_ID,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.Tasks)]
|
||||
public void TaskStarted(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
@@ -394,8 +477,8 @@ namespace System.Threading.Tasks
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
/// <param name="IsExceptional">Whether the task completed due to an error.</param>
|
||||
[SecuritySafeCritical]
|
||||
[Event(TASKCOMPLETED_ID, Version=1, Task = TplEtwProvider.Tasks.TaskExecute, Opcode = EventOpcode.Stop,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.Tasks)]
|
||||
[Event(TASKCOMPLETED_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.TaskStops)]
|
||||
public void TaskCompleted(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int TaskID, bool IsExceptional)
|
||||
@@ -420,7 +503,7 @@ namespace System.Threading.Tasks
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TaskWaitBegin
|
||||
#region TaskWaitBegin
|
||||
/// <summary>
|
||||
/// Fired when starting to wait for a taks's completion explicitly or implicitly.
|
||||
/// </summary>
|
||||
@@ -428,18 +511,21 @@ namespace System.Threading.Tasks
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
/// <param name="Behavior">Configured behavior for the wait.</param>
|
||||
/// <param name="ContinueWithTaskID">If known, if 'TaskID' has a 'continueWith' task, mention give its ID here.
|
||||
/// 0 means unknown. This allows better visualization of the common sequential chaining case.</param>
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
[Event(TASKWAITBEGIN_ID, Version=1, Task = TplEtwProvider.Tasks.TaskWait, Opcode = EventOpcode.Send,
|
||||
[Event(TASKWAITBEGIN_ID, Version=3, Task = TplEtwProvider.Tasks.TaskWait, Opcode = EventOpcode.Send,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
|
||||
public void TaskWaitBegin(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int TaskID, TaskWaitBehavior Behavior)
|
||||
int TaskID, TaskWaitBehavior Behavior, int ContinueWithTaskID, int appDomain)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
EventData* eventPayload = stackalloc EventData[4];
|
||||
EventData* eventPayload = stackalloc EventData[5];
|
||||
eventPayload[0].Size = sizeof(int);
|
||||
eventPayload[0].DataPointer = ((IntPtr)(&OriginatingTaskSchedulerID));
|
||||
eventPayload[1].Size = sizeof(int);
|
||||
@@ -448,21 +534,27 @@ namespace System.Threading.Tasks
|
||||
eventPayload[2].DataPointer = ((IntPtr)(&TaskID));
|
||||
eventPayload[3].Size = sizeof(int);
|
||||
eventPayload[3].DataPointer = ((IntPtr)(&Behavior));
|
||||
Guid childActivityId = CreateGuidForTaskID(TaskID);
|
||||
WriteEventWithRelatedActivityIdCore(TASKWAITBEGIN_ID, &childActivityId, 4, eventPayload);
|
||||
eventPayload[4].Size = sizeof(int);
|
||||
eventPayload[4].DataPointer = ((IntPtr)(&ContinueWithTaskID));
|
||||
if (TasksSetActivityIds)
|
||||
{
|
||||
Guid childActivityId = CreateGuidForTaskID(TaskID);
|
||||
WriteEventWithRelatedActivityIdCore(TASKWAITBEGIN_ID, &childActivityId, 5, eventPayload);
|
||||
}
|
||||
else
|
||||
WriteEventCore(TASKWAITBEGIN_ID, 5, eventPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TaskWaitEnd
|
||||
/// <summary>
|
||||
/// Fired when the wait for a tasks completion returns.
|
||||
/// </summary>
|
||||
/// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
[Event(TASKWAITEND_ID, Task = TplEtwProvider.Tasks.TaskWait, Opcode = EventOpcode.Stop,
|
||||
[Event(TASKWAITEND_ID,
|
||||
Level = EventLevel.Verbose, Keywords = Keywords.Tasks)]
|
||||
public void TaskWaitEnd(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
@@ -473,6 +565,36 @@ namespace System.Threading.Tasks
|
||||
WriteEvent(TASKWAITEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, TaskID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the the work (method) associated with a TaskWaitEnd completes
|
||||
/// </summary>
|
||||
/// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
[Event(TASKWAITCONTINUATIONCOMPLETE_ID,
|
||||
Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
|
||||
public void TaskWaitContinuationComplete(int TaskID)
|
||||
{
|
||||
// Log an event if indicated.
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
|
||||
WriteEvent(TASKWAITCONTINUATIONCOMPLETE_ID, TaskID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the the work (method) associated with a TaskWaitEnd completes
|
||||
/// </summary>
|
||||
/// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
|
||||
/// <param name="OriginatingTaskID">The task ID.</param>
|
||||
/// <param name="TaskID">The task ID.</param>
|
||||
[Event(TASKWAITCONTINUATIONSTARTED_ID,
|
||||
Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
|
||||
public void TaskWaitContinuationStarted(int TaskID)
|
||||
{
|
||||
// Log an event if indicated.
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
|
||||
WriteEvent(TASKWAITCONTINUATIONSTARTED_ID, TaskID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the an asynchronous continuation for a task is scheduled
|
||||
/// </summary>
|
||||
@@ -484,7 +606,7 @@ namespace System.Threading.Tasks
|
||||
Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
|
||||
public void AwaitTaskContinuationScheduled(
|
||||
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
|
||||
int continuationId)
|
||||
int ContinuwWithTaskId)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
|
||||
{
|
||||
@@ -496,13 +618,131 @@ namespace System.Threading.Tasks
|
||||
eventPayload[1].Size = sizeof(int);
|
||||
eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
|
||||
eventPayload[2].Size = sizeof(int);
|
||||
eventPayload[2].DataPointer = ((IntPtr) (&continuationId));
|
||||
Guid continuationActivityId = CreateGuidForTaskID(continuationId);
|
||||
WriteEventWithRelatedActivityIdCore(AWAITTASKCONTINUATIONSCHEDULED_ID, &continuationActivityId, 3, eventPayload);
|
||||
eventPayload[2].DataPointer = ((IntPtr) (&ContinuwWithTaskId));
|
||||
if (TasksSetActivityIds)
|
||||
{
|
||||
Guid continuationActivityId = CreateGuidForTaskID(ContinuwWithTaskId);
|
||||
WriteEventWithRelatedActivityIdCore(AWAITTASKCONTINUATIONSCHEDULED_ID, &continuationActivityId, 3, eventPayload);
|
||||
}
|
||||
else
|
||||
WriteEventCore(AWAITTASKCONTINUATIONSCHEDULED_ID, 3, eventPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[Event(TRACEOPERATIONSTART_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)]
|
||||
public void TraceOperationBegin(int TaskID, string OperationName, long RelatedContext)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityOperation))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed(char* operationNamePtr = OperationName)
|
||||
{
|
||||
EventData* eventPayload = stackalloc EventData[3];
|
||||
eventPayload[0].Size = sizeof(int);
|
||||
eventPayload[0].DataPointer = ((IntPtr) (&TaskID));
|
||||
|
||||
eventPayload[1].Size = ((OperationName.Length + 1) * 2);
|
||||
eventPayload[1].DataPointer = ((IntPtr) operationNamePtr);
|
||||
|
||||
eventPayload[2].Size = sizeof(long);
|
||||
eventPayload[2].DataPointer = ((IntPtr) (&RelatedContext));
|
||||
WriteEventCore(TRACEOPERATIONSTART_ID, 3, eventPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[Event(TRACEOPERATIONRELATION_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityRelation)]
|
||||
public void TraceOperationRelation(int TaskID, CausalityRelation Relation)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityRelation))
|
||||
WriteEvent(TRACEOPERATIONRELATION_ID, TaskID,(int) Relation); // optmized overload for this exists
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[Event(TRACEOPERATIONSTOP_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)]
|
||||
public void TraceOperationEnd(int TaskID, AsyncCausalityStatus Status)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityOperation))
|
||||
WriteEvent(TRACEOPERATIONSTOP_ID, TaskID,(int) Status); // optmized overload for this exists
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[Event(TRACESYNCHRONOUSWORKSTART_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)]
|
||||
public void TraceSynchronousWorkBegin(int TaskID, CausalitySynchronousWork Work)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalitySynchronousWork))
|
||||
WriteEvent(TRACESYNCHRONOUSWORKSTART_ID, TaskID,(int) Work); // optmized overload for this exists
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[Event(TRACESYNCHRONOUSWORKSTOP_ID, Version=1,
|
||||
Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)]
|
||||
public void TraceSynchronousWorkEnd(CausalitySynchronousWork Work)
|
||||
{
|
||||
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalitySynchronousWork))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
EventData* eventPayload = stackalloc EventData[1];
|
||||
eventPayload[0].Size = sizeof(int);
|
||||
eventPayload[0].DataPointer = ((IntPtr) (&Work));
|
||||
|
||||
WriteEventCore(TRACESYNCHRONOUSWORKSTOP_ID, 1, eventPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[NonEvent, System.Security.SecuritySafeCritical]
|
||||
unsafe public void RunningContinuation(int TaskID, object Object) { RunningContinuation(TaskID, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
|
||||
[Event(20, Keywords = Keywords.Debug)]
|
||||
private void RunningContinuation(int TaskID, long Object)
|
||||
{
|
||||
if (Debug)
|
||||
WriteEvent(20, TaskID, Object);
|
||||
}
|
||||
|
||||
[NonEvent, System.Security.SecuritySafeCritical]
|
||||
unsafe public void RunningContinuationList(int TaskID, int Index, object Object) { RunningContinuationList(TaskID, Index, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
|
||||
|
||||
[Event(21, Keywords = Keywords.Debug)]
|
||||
public void RunningContinuationList(int TaskID, int Index, long Object)
|
||||
{
|
||||
if (Debug)
|
||||
WriteEvent(21, TaskID, Index, Object);
|
||||
}
|
||||
|
||||
[Event(22, Keywords = Keywords.Debug)]
|
||||
public void DebugMessage(string Message) { WriteEvent(22, Message); }
|
||||
|
||||
[Event(23, Keywords = Keywords.Debug)]
|
||||
public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(23, Facility, Message); }
|
||||
|
||||
[Event(24, Keywords = Keywords.Debug)]
|
||||
public void DebugFacilityMessage1(string Facility, string Message, string Value1) { WriteEvent(24, Facility, Message, Value1); }
|
||||
|
||||
[Event(25, Keywords = Keywords.DebugActivityId)]
|
||||
public void SetActivityId(Guid NewId)
|
||||
{
|
||||
if (DebugActivityId)
|
||||
WriteEvent(25, NewId);
|
||||
}
|
||||
|
||||
[Event(26, Keywords = Keywords.Debug)]
|
||||
public void NewID(int TaskID)
|
||||
{
|
||||
if (Debug)
|
||||
WriteEvent(26, TaskID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activity IDs are GUIDS but task IDS are integers (and are not unique across appdomains
|
||||
/// This routine creates a process wide unique GUID given a task ID
|
||||
@@ -515,12 +755,10 @@ namespace System.Threading.Tasks
|
||||
// These were generated by CreateGuid, and are reasonably random (and thus unlikley to collide
|
||||
uint pid = EventSource.s_currentPid;
|
||||
int appDomainID = System.Threading.Thread.GetDomainID();
|
||||
return new Guid(taskID,
|
||||
(short) appDomainID , (short) (appDomainID >> 16),
|
||||
(byte)pid, (byte)(pid >> 8), (byte)(pid >> 16), (byte)(pid >> 24),
|
||||
0xff, 0xdc, 0xd7, 0xb5);
|
||||
return new Guid(taskID,
|
||||
(short) appDomainID , (short) (appDomainID >> 16),
|
||||
(byte)pid, (byte)(pid >> 8), (byte)(pid >> 16), (byte)(pid >> 24),
|
||||
0xff, 0xdc, 0xd7, 0xb5);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endif // !FEATURE_PAL
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
75e440fcf3ba1400690187ba89cc60e368eb072c
|
||||
1e3f9293f7c31efdabd588b569ba8cd587752795
|
||||
@@ -343,9 +343,9 @@ namespace System.Threading.Tasks
|
||||
}
|
||||
|
||||
// Enables a token to be stored into the canceled task
|
||||
internal bool TrySetCanceled(CancellationToken tokenToRecord)
|
||||
public bool TrySetCanceled(CancellationToken cancellationToken)
|
||||
{
|
||||
bool rval = m_task.TrySetCanceled(tokenToRecord);
|
||||
bool rval = m_task.TrySetCanceled(cancellationToken);
|
||||
if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
|
||||
return rval;
|
||||
}
|
||||
|
||||
@@ -307,7 +307,6 @@ namespace System.Threading.Tasks
|
||||
m_task = task;
|
||||
m_options = options;
|
||||
m_taskScheduler = scheduler;
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR
|
||||
if (AsyncCausalityTracer.LoggingOn)
|
||||
AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, m_task.Id, "Task.ContinueWith: " + ((Delegate)task.m_action).Method.Name, 0);
|
||||
|
||||
@@ -315,7 +314,6 @@ namespace System.Threading.Tasks
|
||||
{
|
||||
Task.AddToActiveTasks(m_task);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Invokes the continuation for the target completion task.</summary>
|
||||
@@ -340,8 +338,6 @@ namespace System.Threading.Tasks
|
||||
Task continuationTask = m_task;
|
||||
if (isRightKind)
|
||||
{
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR
|
||||
//If the task was cancel before running (e.g a ContinueWhenAll with a cancelled caancelation token)
|
||||
//we will still flow it to ScheduleAndStart() were it will check the status before running
|
||||
//We check here to avoid faulty logs that contain a join event to an operation that was already set as completed.
|
||||
@@ -350,7 +346,6 @@ namespace System.Threading.Tasks
|
||||
// Log now that we are sure that this continuation is being ran
|
||||
AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, continuationTask.Id, CausalityRelation.AssignDelegate);
|
||||
}
|
||||
#endif
|
||||
continuationTask.m_taskScheduler = m_taskScheduler;
|
||||
|
||||
// Either run directly or just queue it up for execution, depending
|
||||
@@ -426,7 +421,7 @@ namespace System.Threading.Tasks
|
||||
// Otherwise, Post the action back to the SynchronizationContext.
|
||||
else
|
||||
{
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
TplEtwProvider etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.IsEnabled())
|
||||
{
|
||||
@@ -445,21 +440,19 @@ namespace System.Threading.Tasks
|
||||
private static void PostAction(object state)
|
||||
{
|
||||
var c = (SynchronizationContextAwaitTaskContinuation)state;
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
TplEtwProvider etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.IsEnabled() && c.m_continuationId != 0)
|
||||
if (etwLog.TasksSetActivityIds && c.m_continuationId != 0)
|
||||
{
|
||||
c.m_syncContext.Post(s_postCallback, GetActionLogDelegate(c.m_continuationId, c.m_action));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
c.m_syncContext.Post(s_postCallback, c.m_action); // s_postCallback is manually cached, as the compiler won't in a SecurityCritical method
|
||||
}
|
||||
}
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
private static Action GetActionLogDelegate(int continuationId, Action action)
|
||||
{
|
||||
return () =>
|
||||
@@ -472,15 +465,12 @@ namespace System.Threading.Tasks
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>Gets a cached delegate for the PostAction method.</summary>
|
||||
/// <returns>
|
||||
/// A delegate for PostAction, which expects a SynchronizationContextAwaitTaskContinuation
|
||||
/// to be passed as state.
|
||||
/// </returns>
|
||||
#if !FEATURE_CORECLR
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#endif
|
||||
[SecurityCritical]
|
||||
private static ContextCallback GetPostActionCallback()
|
||||
{
|
||||
@@ -560,9 +550,7 @@ namespace System.Threading.Tasks
|
||||
/// <summary>The action to invoke.</summary>
|
||||
protected readonly Action m_action;
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
protected int m_continuationId;
|
||||
#endif
|
||||
|
||||
/// <summary>Initializes the continuation.</summary>
|
||||
/// <param name="action">The action to invoke. Must not be null.</param>
|
||||
@@ -630,7 +618,7 @@ namespace System.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
TplEtwProvider etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.IsEnabled())
|
||||
{
|
||||
@@ -679,44 +667,44 @@ namespace System.Threading.Tasks
|
||||
[SecurityCritical]
|
||||
void ExecuteWorkItemHelper()
|
||||
{
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
var etwLog = TplEtwProvider.Log;
|
||||
Guid savedActivityId = Guid.Empty;
|
||||
if (etwLog.IsEnabled() && m_continuationId != 0)
|
||||
if (etwLog.TasksSetActivityIds && m_continuationId != 0)
|
||||
{
|
||||
Guid activityId = TplEtwProvider.CreateGuidForTaskID(m_continuationId);
|
||||
System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out savedActivityId);
|
||||
}
|
||||
#endif
|
||||
try
|
||||
{
|
||||
#endif
|
||||
// We're not inside of a task, so t_currentTask doesn't need to be specially maintained.
|
||||
// We're on a thread pool thread with no higher-level callers, so exceptions can just propagate.
|
||||
// We're not inside of a task, so t_currentTask doesn't need to be specially maintained.
|
||||
// We're on a thread pool thread with no higher-level callers, so exceptions can just propagate.
|
||||
|
||||
// If there's no execution context, just invoke the delegate.
|
||||
if (m_capturedContext == null)
|
||||
{
|
||||
m_action();
|
||||
}
|
||||
// If there is an execution context, get the cached delegate and run the action under the context.
|
||||
else
|
||||
{
|
||||
try
|
||||
// If there's no execution context, just invoke the delegate.
|
||||
if (m_capturedContext == null)
|
||||
{
|
||||
ExecutionContext.Run(m_capturedContext, GetInvokeActionCallback(), m_action, true);
|
||||
m_action();
|
||||
}
|
||||
// If there is an execution context, get the cached delegate and run the action under the context.
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecutionContext.Run(m_capturedContext, GetInvokeActionCallback(), m_action, true);
|
||||
}
|
||||
finally { m_capturedContext.Dispose(); }
|
||||
}
|
||||
finally { m_capturedContext.Dispose(); }
|
||||
}
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (etwLog.IsEnabled() && m_continuationId != 0)
|
||||
#if !MONO
|
||||
if (etwLog.TasksSetActivityIds && m_continuationId != 0)
|
||||
{
|
||||
System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
@@ -724,9 +712,9 @@ namespace System.Threading.Tasks
|
||||
{
|
||||
// inline the fast path
|
||||
if (m_capturedContext == null
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
&& !TplEtwProvider.Log.IsEnabled()
|
||||
#endif
|
||||
#if !MONO
|
||||
&& !TplEtwProvider.Log.IsEnabled()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
m_action();
|
||||
@@ -752,9 +740,7 @@ namespace System.Threading.Tasks
|
||||
[SecurityCritical]
|
||||
private static void InvokeAction(object state) { ((Action)state)(); }
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#endif
|
||||
[SecurityCritical]
|
||||
protected static ContextCallback GetInvokeActionCallback()
|
||||
{
|
||||
@@ -850,8 +836,7 @@ namespace System.Threading.Tasks
|
||||
internal static void UnsafeScheduleAction(Action action, Task task)
|
||||
{
|
||||
AwaitTaskContinuation atc = new AwaitTaskContinuation(action, flowExecutionContext: false);
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR // PAL and CoreClr don't support eventing
|
||||
#if !MONO
|
||||
var etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.IsEnabled() && task != null)
|
||||
{
|
||||
@@ -859,7 +844,6 @@ namespace System.Threading.Tasks
|
||||
etwLog.AwaitTaskContinuationScheduled((task.ExecutingTaskScheduler ?? TaskScheduler.Default).Id, task.Id, atc.m_continuationId);
|
||||
}
|
||||
#endif
|
||||
|
||||
ThreadPool.UnsafeQueueCustomWorkItem(atc, forceGlobal: false);
|
||||
}
|
||||
|
||||
@@ -890,11 +874,7 @@ namespace System.Threading.Tasks
|
||||
internal override Delegate[] GetDelegateContinuationsForDebugger()
|
||||
{
|
||||
Contract.Assert(m_action != null);
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
return new Delegate[] { AsyncMethodBuilderCore.TryGetStateMachineForDebugger(m_action) };
|
||||
#else
|
||||
return new Delegate[] { m_action };
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace System.Threading.Tasks
|
||||
|
||||
private static void EnsureADUnloadCallbackRegistered()
|
||||
{
|
||||
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
|
||||
if (s_adUnloadEventHandler == null &&
|
||||
Interlocked.CompareExchange( ref s_adUnloadEventHandler,
|
||||
AppDomainUnloadCallback,
|
||||
@@ -84,6 +85,7 @@ namespace System.Threading.Tasks
|
||||
{
|
||||
AppDomain.CurrentDomain.DomainUnload += s_adUnloadEventHandler;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void AppDomainUnloadCallback(object sender, EventArgs e)
|
||||
|
||||
@@ -1 +1 @@
|
||||
60e5a447ad78dc121f813b292c8e5dd068691d7d
|
||||
3c8e798e0311370d8c30a814ea22dc3942748e43
|
||||
@@ -215,9 +215,7 @@ namespace System.Threading.Tasks
|
||||
bool bInlined = false;
|
||||
try
|
||||
{
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR
|
||||
task.FireTaskScheduledIfNeeded(this);
|
||||
#endif
|
||||
bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);
|
||||
}
|
||||
finally
|
||||
@@ -272,9 +270,8 @@ namespace System.Threading.Tasks
|
||||
{
|
||||
Contract.Requires(task != null);
|
||||
|
||||
#if !FEATURE_PAL && !FEATURE_CORECLR
|
||||
task.FireTaskScheduledIfNeeded(this);
|
||||
#endif
|
||||
|
||||
this.QueueTask(task);
|
||||
}
|
||||
|
||||
@@ -362,9 +359,7 @@ namespace System.Threading.Tasks
|
||||
{
|
||||
Task currentTask = Task.InternalCurrent;
|
||||
return ( (currentTask != null)
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
&& ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
|
||||
#endif
|
||||
) ? currentTask.ExecutingTaskScheduler : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// ==--==
|
||||
//
|
||||
// <OWNER>[....]</OWNER>
|
||||
// <OWNER>ericeil</OWNER>
|
||||
/*=============================================================================
|
||||
**
|
||||
** Class: ApartmentState
|
||||
|
||||
118
external/referencesource/mscorlib/system/threading/asynclocal.cs
vendored
Normal file
118
external/referencesource/mscorlib/system/threading/asynclocal.cs
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// <OWNER>[....]</OWNER>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Security;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
//
|
||||
// AsyncLocal<T> represents "ambient" data that is local to a given asynchronous control flow, such as an
|
||||
// async method. For example, say you want to associate a culture with a given async flow:
|
||||
//
|
||||
// static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>();
|
||||
//
|
||||
// static async Task SomeOperationAsync(Culture culture)
|
||||
// {
|
||||
// s_currentCulture.Value = culture;
|
||||
//
|
||||
// await FooAsync();
|
||||
// }
|
||||
//
|
||||
// static async Task FooAsync()
|
||||
// {
|
||||
// PrintStringWithCulture(s_currentCulture.Value);
|
||||
// }
|
||||
//
|
||||
// AsyncLocal<T> also provides optional notifications when the value associated with the current thread
|
||||
// changes, either because it was explicitly changed by setting the Value property, or implicitly changed
|
||||
// when the thread encountered an "await" or other context transition. For example, we might want our
|
||||
// current culture to be communicated to the OS as well:
|
||||
//
|
||||
// static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>(
|
||||
// args =>
|
||||
// {
|
||||
// NativeMethods.SetThreadCulture(args.CurrentValue.LCID);
|
||||
// });
|
||||
//
|
||||
public sealed class AsyncLocal<T> : IAsyncLocal
|
||||
{
|
||||
[SecurityCritical] // critical because this action will terminate the process if it throws.
|
||||
private readonly Action<AsyncLocalValueChangedArgs<T>> m_valueChangedHandler;
|
||||
|
||||
//
|
||||
// Constructs an AsyncLocal<T> that does not receive change notifications.
|
||||
//
|
||||
public AsyncLocal()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Constructs an AsyncLocal<T> with a delegate that is called whenever the current value changes
|
||||
// on any thread.
|
||||
//
|
||||
[SecurityCritical]
|
||||
public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
|
||||
{
|
||||
m_valueChangedHandler = valueChangedHandler;
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
[SecuritySafeCritical]
|
||||
get
|
||||
{
|
||||
object obj = ExecutionContext.GetLocalValue(this);
|
||||
return (obj == null) ? default(T) : (T)obj;
|
||||
}
|
||||
[SecuritySafeCritical]
|
||||
set
|
||||
{
|
||||
ExecutionContext.SetLocalValue(this, value, m_valueChangedHandler != null);
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged)
|
||||
{
|
||||
Contract.Assert(m_valueChangedHandler != null);
|
||||
T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj;
|
||||
T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj;
|
||||
m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Interface to allow non-generic code in ExecutionContext to call into the generic AsyncLocal<T> type.
|
||||
//
|
||||
internal interface IAsyncLocal
|
||||
{
|
||||
[SecurityCritical]
|
||||
void OnValueChanged(object previousValue, object currentValue, bool contextChanged);
|
||||
}
|
||||
|
||||
public struct AsyncLocalValueChangedArgs<T>
|
||||
{
|
||||
public T PreviousValue { get; private set; }
|
||||
public T CurrentValue { get; private set; }
|
||||
|
||||
//
|
||||
// If the value changed because we changed to a different ExecutionContext, this is true. If it changed
|
||||
// because someone set the Value property, this is false.
|
||||
//
|
||||
public bool ThreadContextChanged { get; private set; }
|
||||
|
||||
internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
|
||||
: this()
|
||||
{
|
||||
PreviousValue = previousValue;
|
||||
CurrentValue = currentValue;
|
||||
ThreadContextChanged = contextChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// ==--==
|
||||
//
|
||||
// <OWNER>[....]</OWNER>
|
||||
// <OWNER>ericeil</OWNER>
|
||||
/*=============================================================================
|
||||
**
|
||||
** Enum: EventResetMode
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,9 +29,6 @@ namespace System.Threading
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static int Increment(ref int location)
|
||||
{
|
||||
return Add(ref location, 1);
|
||||
@@ -39,9 +36,6 @@ namespace System.Threading
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static long Increment(ref long location)
|
||||
{
|
||||
return Add(ref location, 1);
|
||||
@@ -55,18 +49,12 @@ namespace System.Threading
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static int Decrement(ref int location)
|
||||
{
|
||||
return Add(ref location, -1);
|
||||
}
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static long Decrement(ref long location)
|
||||
{
|
||||
return Add(ref location, -1);
|
||||
@@ -103,13 +91,11 @@ namespace System.Threading
|
||||
[System.Security.SecuritySafeCritical]
|
||||
public static extern double Exchange(ref double location1, double value);
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[System.Security.SecuritySafeCritical]
|
||||
public static extern Object Exchange(ref Object location1, Object value);
|
||||
#endif
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
@@ -242,18 +228,12 @@ namespace System.Threading
|
||||
internal static extern long ExchangeAdd(ref long location1, long value);
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static int Add(ref int location1, int value)
|
||||
{
|
||||
return ExchangeAdd(ref location1, value) + value;
|
||||
}
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static long Add(ref long location1, long value)
|
||||
{
|
||||
return ExchangeAdd(ref location1, value) + value;
|
||||
@@ -268,9 +248,6 @@ namespace System.Threading
|
||||
}
|
||||
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static void MemoryBarrier()
|
||||
{
|
||||
Thread.MemoryBarrier();
|
||||
|
||||
@@ -52,9 +52,6 @@ namespace System.Threading {
|
||||
// could be uninitialized if we threw an exception in our prolog.
|
||||
// The JIT should inline this method to allow check of lockTaken argument to be optimized out
|
||||
// in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static void Enter(Object obj, ref bool lockTaken)
|
||||
{
|
||||
if (lockTaken)
|
||||
@@ -107,9 +104,6 @@ namespace System.Threading {
|
||||
|
||||
// The JIT should inline this method to allow check of lockTaken argument to be optimized out
|
||||
// in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static void TryEnter(Object obj, ref bool lockTaken)
|
||||
{
|
||||
if (lockTaken)
|
||||
@@ -128,9 +122,6 @@ namespace System.Threading {
|
||||
=========================================================================*/
|
||||
// The JIT should inline this method to allow check of lockTaken argument to be optimized out
|
||||
// in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static bool TryEnter(Object obj, int millisecondsTimeout)
|
||||
{
|
||||
bool lockTaken = false;
|
||||
@@ -153,9 +144,6 @@ namespace System.Threading {
|
||||
|
||||
// The JIT should inline this method to allow check of lockTaken argument to be optimized out
|
||||
// in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
|
||||
#if !FEATURE_CORECLR
|
||||
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
|
||||
#endif
|
||||
public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
|
||||
{
|
||||
if (lockTaken)
|
||||
|
||||
@@ -40,18 +40,6 @@ namespace System.Threading
|
||||
{
|
||||
static bool dummyBool;
|
||||
|
||||
#if FEATURE_MACL
|
||||
// Enables workaround for known OS bug at
|
||||
// http://support.microsoft.com/default.aspx?scid=kb;en-us;889318
|
||||
// Calls to OpenMutex and CloseHandle on a mutex must essentially be serialized
|
||||
// to avoid a bug in which the mutex allows multiple entries.
|
||||
static Mutex s_ReservedMutex = null;
|
||||
|
||||
// an arbitrary, reserved name.
|
||||
//
|
||||
const string c_ReservedMutexName = "Global\\CLR_RESERVED_MUTEX_NAME";
|
||||
#endif
|
||||
|
||||
#if !FEATURE_MACL
|
||||
public class MutexSecurity {
|
||||
}
|
||||
@@ -113,6 +101,9 @@ namespace System.Threading
|
||||
#if FEATURE_LEGACYNETCF
|
||||
static string WinCEObjectNameQuirk(string name)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
// WinCE allowed backslashes in kernel object names, but WinNT does not allow them.
|
||||
// Replace all backslashes with a rare unicode character if we are in NetCF compat mode.
|
||||
// Mutex was the only named kernel object exposed to phone apps, so we do not have
|
||||
@@ -205,7 +196,6 @@ namespace System.Threading
|
||||
}
|
||||
m_newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS;
|
||||
m_mutex.SetHandleInternal(mutexHandle);
|
||||
mutexHandle.SetAsMutex();
|
||||
|
||||
m_mutex.hasThreadAffinity = true;
|
||||
|
||||
@@ -292,7 +282,6 @@ namespace System.Threading
|
||||
private Mutex(SafeWaitHandle handle)
|
||||
{
|
||||
SetHandleInternal(handle);
|
||||
handle.SetAsMutex();
|
||||
hasThreadAffinity = true;
|
||||
}
|
||||
|
||||
@@ -444,7 +433,6 @@ namespace System.Threading
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) {
|
||||
int errorCode;
|
||||
bool fReservedMutexObtained = false;
|
||||
bool fAffinity = false;
|
||||
|
||||
while(true) {
|
||||
@@ -472,7 +460,6 @@ namespace System.Threading
|
||||
#endif
|
||||
fAffinity = true;
|
||||
}
|
||||
AcquireReservedMutex(ref fReservedMutexObtained);
|
||||
mutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);
|
||||
if(!mutexHandle.IsInvalid)
|
||||
{
|
||||
@@ -485,9 +472,6 @@ namespace System.Threading
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fReservedMutexObtained)
|
||||
ReleaseReservedMutex();
|
||||
|
||||
if (fAffinity) {
|
||||
#if !FEATURE_CORECLR
|
||||
Thread.EndThreadAffinity();
|
||||
@@ -529,98 +513,5 @@ namespace System.Threading
|
||||
}
|
||||
#endif
|
||||
|
||||
// Enables workaround for known OS bug at
|
||||
// http://support.microsoft.com/default.aspx?scid=kb;en-us;889318
|
||||
// One machine-wide mutex serializes all OpenMutex and CloseHandle operations.
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
#if !FEATURE_CORECLR
|
||||
[SecurityPermission(SecurityAction.Assert, ControlPrincipal = true)]
|
||||
#endif
|
||||
internal static unsafe void AcquireReservedMutex(ref bool bHandleObtained)
|
||||
{
|
||||
#if FEATURE_MACL
|
||||
SafeWaitHandle mutexHandle = null;
|
||||
int errorCode;
|
||||
|
||||
bHandleObtained = false;
|
||||
|
||||
if (!Environment.IsW2k3) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_ReservedMutex == null) {
|
||||
|
||||
// Create a maximally-permissive security descriptor, to ensure we never get an
|
||||
// ACCESS_DENIED error when calling CreateMutex
|
||||
MutexSecurity sec = new MutexSecurity();
|
||||
SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
|
||||
sec.AddAccessRule(new MutexAccessRule(everyoneSid, MutexRights.FullControl, AccessControlType.Allow));
|
||||
|
||||
// For ACL's, get the security descriptor from the MutexSecurity.
|
||||
Win32Native.SECURITY_ATTRIBUTES secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
|
||||
secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
|
||||
|
||||
byte[] sd = sec.GetSecurityDescriptorBinaryForm();
|
||||
byte * bytesOnStack = stackalloc byte[sd.Length];
|
||||
Buffer.Memcpy(bytesOnStack, 0, sd, 0, sd.Length);
|
||||
secAttrs.pSecurityDescriptor = bytesOnStack;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try {}
|
||||
finally {
|
||||
mutexHandle = Win32Native.CreateMutex(secAttrs, false, c_ReservedMutexName);
|
||||
|
||||
// need to set specially, since this mutex cannot lock on itself while closing itself.
|
||||
mutexHandle.SetAsReservedMutex();
|
||||
}
|
||||
|
||||
errorCode = Marshal.GetLastWin32Error();
|
||||
if (mutexHandle.IsInvalid) {
|
||||
mutexHandle.SetHandleAsInvalid();
|
||||
__Error.WinIOError(errorCode, c_ReservedMutexName);
|
||||
}
|
||||
|
||||
Mutex m = new Mutex(mutexHandle);
|
||||
Interlocked.CompareExchange(ref s_ReservedMutex, m, null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally {
|
||||
try {
|
||||
s_ReservedMutex.WaitOne();
|
||||
bHandleObtained = true;
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
// we don't care if another process holding the Mutex was killed
|
||||
bHandleObtained = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
bHandleObtained = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
internal static void ReleaseReservedMutex()
|
||||
{
|
||||
#if FEATURE_MACL
|
||||
if (!Environment.IsW2k3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Contract.Assert(s_ReservedMutex != null,
|
||||
"ReleaseReservedMutex called without prior call to AcquireReservedMutex!");
|
||||
|
||||
s_ReservedMutex.ReleaseMutex();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user