Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions src/coreclr/vm/threadsuspend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1997,15 +1997,6 @@ CONTEXT* AllocateOSContextHelper(BYTE** contextBuffer)
pfnInitializeContext2(buffer, context, &pOSContext, &contextSize, xStateCompactionMask):
InitializeContext(buffer, context, &pOSContext, &contextSize);

// if AVX is supported set the appropriate features mask in the context
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this removed, the code above that sets the supportAVX based on the FeatureMask can be removed too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, even before supportAVX was redundant, since SetXStateFeaturesMask performs the same check - to filter out what is not supported.

if (success && supportsAVX)
{
// This should not normally fail.
// The system silently ignores any feature specified in the FeatureMask
// which is not enabled on the processor.
success = SetXStateFeaturesMask(pOSContext, XSTATE_MASK_AVX);
}

if (!success)
{
delete[] buffer;
Expand Down Expand Up @@ -2912,9 +2903,23 @@ BOOL Thread::RedirectThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt)

//////////////////////////////////////
// Get and save the thread's context
BOOL bRes = true;

// Always get complete context, pCtx->ContextFlags are set during Initialization
BOOL bRes = EEGetThreadContext(this, pCtx);

#if defined(TARGET_X86) || defined(TARGET_AMD64)
// Scenarios like GC stress may indirectly disable XState features in the pCtx
// depending on the state at the time of GC stress interrupt.
//
// Make sure that AVX feature mask is set, if supported.
//
// This should not normally fail.
// The system silently ignores any feature specified in the FeatureMask
// which is not enabled on the processor.
bRes &= SetXStateFeaturesMask(pCtx, XSTATE_MASK_AVX);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have one nit - I would prefer failures / asserts on each of the failure instead of combining the results together.

Copy link
Member Author

@VSadov VSadov Feb 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetXStateFeaturesMask and SetXStateFeaturesMask basically cannot fail. They are very tolerant to the input.
To get failures you'd need something like pass context flags for a wrong architecture (like arm64). As-is that would not compile.

Realistically only CopyContext is an API with complex requirements and validation that could fail here due to some mistake.
I think in this particular case individual asserts/returns would not add a lot of value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just found those would fail also when passed context without any XSTATE present. It seems like something that could possibly happen for the usage in Thread::RedirectCurrentThreadAtHandledJITCase where we pass it a general context that we get from the vectored exception handler. So it seems that it would be nice to actually make that work in that case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, my read on that was that Set(Get) would be a noop, but I think you are right, if no XState is set it may fail. Arguably a bug in the validation of Set not accepting 0.

Yes, we should make this case work.

#endif //defined(TARGET_X86) || defined(TARGET_AMD64)

bRes &= EEGetThreadContext(this, pCtx);
_ASSERTE(bRes && "Failed to GetThreadContext in RedirectThreadAtHandledJITCase - aborting redirect.");

if (!bRes)
Expand Down Expand Up @@ -3029,9 +3034,25 @@ BOOL Thread::RedirectCurrentThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt, CONT

//////////////////////////////////////
// Get and save the thread's context
BOOL success = CopyContext(pCtx, pCtx->ContextFlags, pCurrentThreadCtx);
BOOL success = true;

#if defined(TARGET_X86) || defined(TARGET_AMD64)
// This method is called for GC stress interrupts in managed code.
// The current context may have various XState features, depending on what is used/dirty,
// but only AVX feature may contain live data. (that could change in the future)
// Besides pCtx may not have space to store other features.
// So we will mask out everything but AVX.
DWORD64 srcFeatures = 0;
success &= GetXStateFeaturesMask(pCurrentThreadCtx, &srcFeatures);
success &= SetXStateFeaturesMask(pCurrentThreadCtx, srcFeatures & XSTATE_MASK_AVX);
#endif //defined(TARGET_X86) || defined(TARGET_AMD64)

success &= CopyContext(pCtx, pCtx->ContextFlags, pCurrentThreadCtx);
_ASSERTE(success);

if (!success)
return FALSE;

// Ensure that this flag is set for the next time through the normal path,
// RedirectThreadAtHandledJITCase.
pCtx->ContextFlags |= CONTEXT_EXCEPTION_REQUEST;
Expand Down