diff --git a/src/Common/src/CoreLib/Internal/Threading/Tasks/AsyncCausalitySupport.cs b/src/Common/src/CoreLib/Internal/Threading/Tasks/AsyncCausalitySupport.cs new file mode 100644 index 000000000000..35f4dfe18c4b --- /dev/null +++ b/src/Common/src/CoreLib/Internal/Threading/Tasks/AsyncCausalitySupport.cs @@ -0,0 +1,57 @@ +// 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.Threading.Tasks; +using System.Runtime.CompilerServices; + +namespace Internal.Threading.Tasks +{ + // + // An internal contract that exposes just enough async debugger support needed by the AsTask() extension methods in the WindowsRuntimeSystemExtensions class. + // + public static class AsyncCausalitySupport + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AddToActiveTasks(Task task) + { + if (Task.s_asyncDebuggingEnabled) + Task.AddToActiveTasks(task); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RemoveFromActiveTasks(Task task) + { + if (Task.s_asyncDebuggingEnabled) + Task.RemoveFromActiveTasks(task.Id); + } + + public static bool LoggingOn + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return AsyncCausalityTracer.LoggingOn; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void TraceOperationCreation(Task task, string operationName) + { + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, task.Id, operationName, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void TraceOperationCompletedSuccess(Task task) + { + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, task.Id, AsyncCausalityStatus.Completed); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void TraceOperationCompletedError(Task task) + { + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, task.Id, AsyncCausalityStatus.Error); + } + } +} + diff --git a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems index 263214af5e63..9a94bdf536be 100644 --- a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems +++ b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems @@ -22,6 +22,7 @@ + @@ -973,6 +974,9 @@ + + + diff --git a/src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index b44df7a0cd6f..f6692e8b43fb 100644 --- a/src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -578,7 +578,7 @@ private void MoveNext(Thread threadPoolThread) bool loggingOn = AsyncCausalitySupport.LoggingOn; if (loggingOn) { - AsyncCausalitySupport.TraceSynchronousWorkStart(this); + AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, this.Id, CausalitySynchronousWork.Execution); } ExecutionContext context = Context; @@ -619,7 +619,7 @@ private void MoveNext(Thread threadPoolThread) if (loggingOn) { - AsyncCausalitySupport.TraceSynchronousWorkCompletion(); + AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution); } } diff --git a/src/Common/src/CoreLib/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs b/src/Common/src/CoreLib/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs new file mode 100644 index 000000000000..c3f787b36b77 --- /dev/null +++ b/src/Common/src/CoreLib/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs @@ -0,0 +1,77 @@ +// 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.Diagnostics; + +namespace System.Threading.Tasks +{ + internal enum CausalityTraceLevel + { + Required = 0, + Important = 1, + Verbose = 2, + } + + internal enum AsyncCausalityStatus + { + Started = 0, + Completed = 1, + Canceled = 2, + Error = 3, + } + + internal enum CausalityRelation + { + AssignDelegate = 0, + Join = 1, + Choice = 2, + Cancel = 3, + Error = 4, + } + + internal enum CausalitySynchronousWork + { + CompletionNotification = 0, + ProgressNotification = 1, + Execution = 2, + } + + // + // Empty implementation of AsyncCausality events + // + internal static class AsyncCausalityTracer + { + public static bool LoggingOn => false; + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void EnableToETW(bool enabled) + { + } + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void TraceOperationCreation(CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext) + { + } + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void TraceOperationCompletion(CausalityTraceLevel traceLevel, int taskId, AsyncCausalityStatus status) + { + } + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void TraceOperationRelation(CausalityTraceLevel traceLevel, int taskId, CausalityRelation relation) + { + } + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, int taskId, CausalitySynchronousWork work) + { + } + + [Conditional("NOOP_ASYNCCASUALITYTRACER")] + public static void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySynchronousWork work) + { + } + } +}