Skip to content

Commit 167d862

Browse files
authored
Save and restore Thread.CurrentThread._synchronizationContext for synchronous runtime async calls (#117725)
This implements the remaining handling: saving and restoring `Thread.CurrentThread._synchronizationContext` around runtime async calls that finish synchronously. Lots of trickiness in representing this in the JIT. We introduce a new "suspended indicator" local that is defined by async calls and that the front end uses when it expands IR that restores the field. Plenty of optimization opportunities remaining, including a simple jump threading optimization we should be able to do to make the suspension indicator variable disappear in common cases (all cases except when resuming with an exception).
1 parent 831523d commit 167d862

File tree

22 files changed

+582
-138
lines changed

22 files changed

+582
-138
lines changed

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -591,19 +591,42 @@ private static ValueTask FinalizeValueTaskReturningThunk(Continuation continuati
591591
}
592592

593593
[MethodImpl(MethodImplOptions.AggressiveInlining)]
594-
private static void RestoreExecutionContext(ExecutionContext? previousExecutionCtx)
594+
private static void RestoreExecutionContext(ExecutionContext? previousExecCtx)
595595
{
596596
Thread thread = Thread.CurrentThreadAssumedInitialized;
597-
ExecutionContext? currentExecutionCtx = thread._executionContext;
598-
if (previousExecutionCtx != currentExecutionCtx)
597+
ExecutionContext? currentExecCtx = thread._executionContext;
598+
if (previousExecCtx != currentExecCtx)
599599
{
600-
ExecutionContext.RestoreChangedContextToThread(thread, previousExecutionCtx, currentExecutionCtx);
600+
ExecutionContext.RestoreChangedContextToThread(thread, previousExecCtx, currentExecCtx);
601601
}
602602
}
603603

604-
private static void CaptureContinuationContext(ref object context, ref CorInfoContinuationFlags flags)
604+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
605+
private static void CaptureContexts(out ExecutionContext? execCtx, out SynchronizationContext? syncCtx)
606+
{
607+
Thread thread = Thread.CurrentThreadAssumedInitialized;
608+
execCtx = thread._executionContext;
609+
syncCtx = thread._synchronizationContext;
610+
}
611+
612+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
613+
private static void RestoreContexts(bool suspended, ExecutionContext? previousExecCtx, SynchronizationContext? previousSyncCtx)
614+
{
615+
Thread thread = Thread.CurrentThreadAssumedInitialized;
616+
if (!suspended && previousSyncCtx != thread._synchronizationContext)
617+
{
618+
thread._synchronizationContext = previousSyncCtx;
619+
}
620+
621+
ExecutionContext? currentExecCtx = thread._executionContext;
622+
if (previousExecCtx != currentExecCtx)
623+
{
624+
ExecutionContext.RestoreChangedContextToThread(thread, previousExecCtx, currentExecCtx);
625+
}
626+
}
627+
628+
private static void CaptureContinuationContext(SynchronizationContext syncCtx, ref object context, ref CorInfoContinuationFlags flags)
605629
{
606-
SynchronizationContext? syncCtx = Thread.CurrentThreadAssumedInitialized._synchronizationContext;
607630
if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
608631
{
609632
flags |= CorInfoContinuationFlags.CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT;

src/coreclr/inc/corinfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,8 @@ struct CORINFO_ASYNC_INFO
17471747
// Method handle for AsyncHelpers.RestoreExecutionContext
17481748
CORINFO_METHOD_HANDLE restoreExecutionContextMethHnd;
17491749
CORINFO_METHOD_HANDLE captureContinuationContextMethHnd;
1750+
CORINFO_METHOD_HANDLE captureContextsMethHnd;
1751+
CORINFO_METHOD_HANDLE restoreContextsMethHnd;
17501752
};
17511753

17521754
// Flags passed from JIT to runtime.

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737

3838
#include <minipal/guid.h>
3939

40-
constexpr GUID JITEEVersionIdentifier = { /* d24a67e0-9e57-4c9e-ad31-5785df2526f2 */
41-
0xd24a67e0,
42-
0x9e57,
43-
0x4c9e,
44-
{0xad, 0x31, 0x57, 0x85, 0xdf, 0x25, 0x26, 0xf2}
40+
constexpr GUID JITEEVersionIdentifier = { /* 2d40ec46-2e41-4a8b-8349-3c1267b95821 */
41+
0x2d40ec46,
42+
0x2e41,
43+
0x4a8b,
44+
{0x83, 0x49, 0x3c, 0x12, 0x67, 0xb9, 0x58, 0x21}
4545
};
4646

4747
#endif // JIT_EE_VERSIONING_GUID_H

0 commit comments

Comments
 (0)