Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Change the PerfMap crst into an UNSAFE_ANYMODE crst by davidwrighton · Pull Request #129021 · dotnet/runtime · GitHub
Skip to content

Change the PerfMap crst into an UNSAFE_ANYMODE crst - #129021

Merged
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst
Jun 8, 2026
Merged

Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
davidwrighton merged 8 commits into
dotnet:mainfrom
davidwrighton:PerfMapUNSAFE_ANYMODECrst

Conversation

@davidwrighton

Copy link
Copy Markdown
Member

And make sure all logic run under the crst is safe for running in such a place

Also, add logic to handle some simple cases where moving to preemptive is fairly simple. Notably, the VirtualCallStub logic needed these fixes.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts CoreCLR’s perfmap logging synchronization to avoid GC-mode toggle deadlocks by switching the PerfMap lock to CRST_UNSAFE_ANYMODE, and updates VSD (virtual call stub) stub-generation paths to safely enter preemptive mode where needed when perfmap logging is enabled.

Changes:

  • Switch PerfMap’s s_csPerfMap to CRST_UNSAFE_ANYMODE to avoid deadlock cycles involving GC-mode toggles during lock acquisition.
  • Update VirtualCallStubManager stub-generation call sites to temporarily enter preemptive GC mode when perfmap logging is enabled, and reinitialize hash probers after mode transitions.
  • Add a non-FEATURE_PERFMAP stub PerfMap implementation in perfmap.h so call sites can compile without #ifdef FEATURE_PERFMAP wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

FileDescription
src/coreclr/vm/virtualcallstub.cppWrap specific stub-generation paths in GCX_MAYBE_PREEMP when perfmap is enabled, and reset probers after potential invalidation.
src/coreclr/vm/perfmap.hAdd a stub PerfMap class for builds where FEATURE_PERFMAP is not defined.
src/coreclr/vm/perfmap.cppInitialize the PerfMap lock as CRST_UNSAFE_ANYMODE and slightly reduce time holding the lock in LogPreCompiledMethod.

Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
CopilotAI review requested due to automatic review settings June 5, 2026 22:17

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.h
Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
CopilotAI review requested due to automatic review settings June 8, 2026 17:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/vm/virtualcallstub.cpp
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.cpp Outdated
CopilotAI review requested due to automatic review settings June 8, 2026 17:54
Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/vm/perfmap.h
@davidwrighton
davidwrighton merged commit 1b366f4 into dotnet:mainJun 8, 2026
107 of 111 checks passed
@davidwrighton

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@davidwrighton backporting to release/10.0 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosUsing index info to reconstruct a base tree...M	src/coreclr/vm/perfmap.cppM	src/coreclr/vm/perfmap.hM	src/coreclr/vm/virtualcallstub.cppFalling back to patching base and 3-way merge...Auto-merging src/coreclr/vm/perfmap.cppCONFLICT (content): Merge conflict in src/coreclr/vm/perfmap.cppAuto-merging src/coreclr/vm/perfmap.hAuto-merging src/coreclr/vm/virtualcallstub.cpperror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0001 Add logic to handle some simple cases where moving to preemptive is more ideal for perfmap scenariosError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

davidwrighton added a commit to davidwrighton/runtime that referenced this pull request Jun 8, 2026
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview6 milestone Jun 9, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jun 15, 2026
…129142)
Backport of #129021 to release/10.0
Fixes#128401
/cc @leculver ## Customer Impact
- [x] Customer reported
- [ ] Found internally
This was reported by customers which found that a service in production
would deadlock occasionally when perfmap generation was enabled.
## Regression
- [x] Yes
- [ ] No
This was introduced in #113943
## Testing
Fix was verified through analysis, and the fix also includes an escape
hatch environment variable (DOTNET_PerfMapGranularity=4) which will
disable the problematic code entirely.
## Risk
1. This fix is only applicable to customers which use perfmaps
2. The fix not only includes code changes which fix the deadlock problem
from happening, but also includes a change to add a config switch to
avoid the problematic code entirely while keeping the perfmap generation
for most scenarios which are interesting to customers.
Risks:
This fix adjusts a lock so that it will not switch to preemptive mode,
and we will run some file I/O while under that lock. This may cause GC
latency spikes on some customer workloads. This issue is mitigated by
the new switch which can be used to avoid the problem in its entirety at
the cost of slightly less accurate profile data for a limited set of
scenarios.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 10, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@davidwrighton@noahfalk@jkotas