Skip to content

Commit c04933d

Browse files
authored
[NativeAOT] Allow reverse pinvoke in DoNotTriggerGc thread state regardless of coop mode. (#85435)
* Allow reverse pinvoke in DoNotTriggerGc thread state regardless of coop mode. * do not attach DoNotTriggerGc threads in reverse pinvoke * propagate useful msbuild arguments to the build * more PR feedback. * a nit - more consistent formatting * Do not pass through StripSymbols
1 parent c46c5b8 commit c04933d

File tree

3 files changed

+20
-20
lines changed

3 files changed

+20
-20
lines changed

src/coreclr/nativeaot/Runtime/EHHelpers.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,10 @@ EXTERN_C int32_t __stdcall RhpPInvokeExceptionGuard(PEXCEPTION_RECORD pExc
202202

203203
Thread * pThread = ThreadStore::GetCurrentThread();
204204

205-
// If the thread is currently in the "do not trigger GC" mode, we must not allocate, we must not reverse pinvoke, or
206-
// return from a pinvoke. All of these things will deadlock with the GC and they all become increasingly likely as
207-
// exception dispatch kicks off. So we just address this as early as possible with a FailFast. The most
208-
// likely case where this occurs is in our GC-callouts for Jupiter lifetime management -- in that case, we have
209-
// managed code that calls to native code (without pinvoking) which might have a bug that causes an AV.
205+
// A thread in DoNotTriggerGc mode has many restrictions that will become increasingly likely to be violated as
206+
// exception dispatch kicks off. So we just address this as early as possible with a FailFast.
207+
// The most likely case where this occurs is in GC-callouts -- in that case, we have
208+
// managed code that runs on behalf of GC, which might have a bug that causes an AV.
210209
if (pThread->IsDoNotTriggerGcSet())
211210
RhFailFast();
212211

src/coreclr/nativeaot/Runtime/thread.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,34 +1125,33 @@ EXTERN_C NATIVEAOT_API uint32_t __cdecl RhCompatibleReentrantWaitAny(UInt32_BOOL
11251125

11261126
FORCEINLINE bool Thread::InlineTryFastReversePInvoke(ReversePInvokeFrame * pFrame)
11271127
{
1128-
// Do we need to attach the thread?
1129-
if (!IsStateSet(TSF_Attached))
1130-
return false; // thread is not attached
1128+
// remember the current transition frame, so it will be restored when we return from reverse pinvoke
1129+
pFrame->m_savedPInvokeTransitionFrame = m_pTransitionFrame;
11311130

11321131
// If the thread is already in cooperative mode, this is a bad transition that will be a fail fast unless we are in
11331132
// a do not trigger mode. The exception to the rule allows us to have [UnmanagedCallersOnly] methods that are called via
11341133
// the "restricted GC callouts" as well as from native, which is necessary because the methods are CCW vtable
11351134
// methods on interfaces passed to native.
1136-
if (IsCurrentThreadInCooperativeMode())
1135+
// We will allow threads in DoNotTriggerGc mode to do reverse PInvoke regardless of their coop state.
1136+
if (IsDoNotTriggerGcSet())
11371137
{
1138-
if (IsDoNotTriggerGcSet())
1139-
{
1140-
// RhpTrapThreads will always be set in this case, so we must skip that check. We must be sure to
1141-
// zero-out our 'previous transition frame' state first, however.
1142-
pFrame->m_savedPInvokeTransitionFrame = NULL;
1143-
return true;
1144-
}
1138+
// We expect this scenario only when EE is stopped.
1139+
ASSERT(ThreadStore::IsTrapThreadsRequested());
1140+
// no need to do anything
1141+
return true;
1142+
}
11451143

1144+
// Do we need to attach the thread?
1145+
if (!IsStateSet(TSF_Attached))
1146+
return false; // thread is not attached
1147+
1148+
if (IsCurrentThreadInCooperativeMode())
11461149
return false; // bad transition
1147-
}
11481150

11491151
// this is an ordinary transition to managed code
11501152
// GC threads should not do that
11511153
ASSERT(!IsGCSpecial());
11521154

1153-
// save the previous transition frame
1154-
pFrame->m_savedPInvokeTransitionFrame = m_pTransitionFrame;
1155-
11561155
// must be in cooperative mode when checking the trap flag
11571156
VolatileStoreWithoutBarrier(&m_pTransitionFrame, NULL);
11581157

@@ -1233,6 +1232,7 @@ FORCEINLINE void Thread::InlineReversePInvokeReturn(ReversePInvokeFrame * pFrame
12331232

12341233
FORCEINLINE void Thread::InlinePInvoke(PInvokeTransitionFrame * pFrame)
12351234
{
1235+
ASSERT(!IsDoNotTriggerGcSet() || ThreadStore::IsTrapThreadsRequested());
12361236
pFrame->m_pThread = this;
12371237
// set our mode to preemptive
12381238
VolatileStoreWithoutBarrier(&m_pTransitionFrame, pFrame);

src/tests/build.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@
581581
<GroupBuildCmd>$(GroupBuildCmd) "/p:PackageOS=$(PackageOS)"</GroupBuildCmd>
582582
<GroupBuildCmd>$(GroupBuildCmd) "/p:RuntimeFlavor=$(RuntimeFlavor)"</GroupBuildCmd>
583583
<GroupBuildCmd>$(GroupBuildCmd) "/p:RuntimeVariant=$(RuntimeVariant)"</GroupBuildCmd>
584+
<GroupBuildCmd Condition="'$(ServerGarbageCollection)' != ''">$(GroupBuildCmd) "/p:ServerGarbageCollection=$(ServerGarbageCollection)"</GroupBuildCmd>
584585
<GroupBuildCmd>$(GroupBuildCmd) "/p:CLRTestBuildAllTargets=$(CLRTestBuildAllTargets)"</GroupBuildCmd>
585586
<GroupBuildCmd>$(GroupBuildCmd) "/p:UseCodeFlowEnforcement=$(UseCodeFlowEnforcement)"</GroupBuildCmd>
586587
<GroupBuildCmd>$(GroupBuildCmd) "/p:__TestGroupToBuild=$(__TestGroupToBuild)"</GroupBuildCmd>

0 commit comments

Comments
 (0)