Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5.6k
Change the PerfMap crst into an UNSAFE_ANYMODE crst#129021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
4f026574e4a6f695630a4fa3cfe62f6a3cd3e68fd624362931a6c35aFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -33,6 +33,7 @@ PerfMap * PerfMap::s_Current = nullptr; | ||
| bool PerfMap::s_ShowOptimizationTiers = false; | ||
| bool PerfMap::s_GroupStubsOfSameType = false; | ||
| bool PerfMap::s_IndividualAllocationStubReporting = false; | ||
| bool PerfMap::s_LogStubs = false; | ||
| unsigned PerfMap::s_StubsMapped = 0; | ||
| CrstStatic PerfMap::s_csPerfMap; | ||
| @@ -47,7 +48,15 @@ void PerfMap::Initialize() | ||
| { | ||
| LIMITED_METHOD_CONTRACT; | ||
| s_csPerfMap.Init(CrstPerfMap); | ||
| // Use CRST_UNSAFE_ANYMODE to avoid a GC-mode toggle deadlock: callers such as | ||
| // CodeFragmentHeap::RealAllocAlignedMem hold CRST_UNSAFE_ANYMODE locks in cooperative | ||
| // mode. A default Crst here would toggle cooperative->preemptive->acquire->cooperative, | ||
| // and the post-acquire DisablePreemptiveGC can block on a pending GC suspension, | ||
| // forming a deadlock cycle with threads waiting on the outer UNSAFE_ANYMODE lock. | ||
| // All data accessed under this lock is native (FILE*, fd, SString) so holding it | ||
| // in cooperative mode does not introduce new GC-safety issues. Doing I/O | ||
| // in cooperative mode is still less than ideal. | ||
| s_csPerfMap.Init(CrstPerfMap, CrstFlags(CRST_UNSAFE_ANYMODE)); | ||
| PerfMapType perfMapType = (PerfMapType)CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled); | ||
| PerfMap::Enable(perfMapType, false); | ||
| @@ -77,11 +86,16 @@ void PerfMap::InitializeConfiguration() | ||
| DWORD granularity = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapStubGranularity); | ||
| s_GroupStubsOfSameType = (granularity & 1) != 1; | ||
| s_IndividualAllocationStubReporting = (granularity & 2) != 0; | ||
| s_LogStubs = (granularity & 4) == 0; | ||
| } | ||
| void PerfMap::Enable(PerfMapType type, bool sendExisting) | ||
| { | ||
| LIMITED_METHOD_CONTRACT; | ||
| CONTRACTL | ||
| { | ||
| MODE_PREEMPTIVE; | ||
| } | ||
| CONTRACTL_END; | ||
| if (type == PerfMapType::DISABLED) | ||
| { | ||
| @@ -294,8 +308,6 @@ void PerfMap::WriteLine(SString& line) | ||
| void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig) | ||
| { | ||
| LIMITED_METHOD_CONTRACT; | ||
| CONTRACTL{ | ||
| THROWS; | ||
| GC_NOTRIGGER; | ||
| @@ -349,7 +361,12 @@ void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t cod | ||
| // Log a pre-compiled method to the perfmap. | ||
| void PerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) | ||
| { | ||
| LIMITED_METHOD_CONTRACT; | ||
| CONTRACTL | ||
| { | ||
| THROWS; | ||
| MODE_PREEMPTIVE; | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| CONTRACTL_END; | ||
| if (!s_enabled) | ||
| { | ||
| @@ -385,14 +402,14 @@ void PerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) | ||
| if (methodRegionInfo.coldSize > 0) | ||
| { | ||
| CrstHolder ch(&(s_csPerfMap)); | ||
| if (s_ShowOptimizationTiers) | ||
| { | ||
| pMethod->GetFullMethodInfo(name); | ||
| name.Append(W("[PreJit-cold]")); | ||
| } | ||
| CrstHolder ch(&(s_csPerfMap)); | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| PAL_PerfJitDump_LogMethod((void*)methodRegionInfo.coldStartAddress, methodRegionInfo.coldSize, name.GetUTF8(), nullptr, nullptr, /*reportCodeBlock*/true); | ||
| } | ||
| } | ||
| @@ -402,9 +419,14 @@ void PerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) | ||
| // Log a set of stub to the map. | ||
| void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, size_t codeSize, PerfMapStubType stubAllocationType) | ||
| { | ||
| LIMITED_METHOD_CONTRACT; | ||
| CONTRACTL | ||
| { | ||
| GC_NOTRIGGER; | ||
| MODE_ANY; | ||
| } | ||
| CONTRACTL_END; | ||
| if (!s_enabled) | ||
| if (!s_enabled || !s_LogStubs) | ||
| { | ||
| return; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -19,6 +19,52 @@ enum class PerfMapStubType | ||
| Individual | ||
| }; | ||
| #ifndef FEATURE_PERFMAP | ||
| class PerfMap | ||
| { | ||
| public: | ||
| static bool IsEnabled() | ||
| { | ||
| #ifdef DEBUG | ||
| return true; | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| #else | ||
| return false; | ||
| #endif | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig) | ||
| { | ||
| CONTRACTL | ||
| { | ||
| THROWS; | ||
| MODE_PREEMPTIVE; | ||
| } | ||
| CONTRACTL_END; | ||
| } | ||
| static void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) | ||
| { | ||
| CONTRACTL | ||
| { | ||
| THROWS; | ||
| MODE_PREEMPTIVE; | ||
| } | ||
| CONTRACTL_END; | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| static void LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, size_t codeSize, PerfMapStubType stubAllocationType) | ||
| { | ||
| CONTRACTL | ||
| { | ||
| GC_NOTRIGGER; | ||
| MODE_ANY; | ||
| } | ||
| CONTRACTL_END; | ||
| } | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| }; | ||
| #else // FEATURE_PERFMAP | ||
| class PerfMap | ||
| { | ||
| private: | ||
| @@ -36,6 +82,7 @@ class PerfMap | ||
| // Indicate current stub granularity rules | ||
| static bool s_GroupStubsOfSameType; | ||
| static bool s_IndividualAllocationStubReporting; | ||
| static bool s_LogStubs; // If false, do not log stubs at all | ||
| // Set to true if an error is encountered when writing to the file. | ||
| static unsigned s_StubsMapped; | ||
| @@ -112,4 +159,5 @@ class PerfMap | ||
| static bool LowGranularityStubs() { return !s_IndividualAllocationStubReporting; } | ||
| }; | ||
| #endif // FEATURE_PERFMAP | ||
| #endif // PERFPID_H | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -10,9 +10,7 @@ | ||
| #include "comdelegate.h" | ||
| #include <dn-stdio.h> | ||
| #ifdef FEATURE_PERFMAP | ||
| #include "perfmap.h" | ||
| #endif | ||
| #ifndef DACCESS_COMPILE | ||
| @@ -1051,7 +1049,19 @@ PCODE VirtualCallStubManager::GetCallStub(DispatchToken token) | ||
| { | ||
| if ((stub = (PCODE)(lookups->Find(&probeL))) == CALL_STUB_EMPTY_ENTRY) | ||
| { | ||
| LookupHolder *pLookupHolder = GenerateLookupStub(addrOfResolver, token.To_SIZE_T()); | ||
| LookupHolder *pLookupHolder; | ||
| bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| { | ||
| GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); | ||
| pLookupHolder = GenerateLookupStub(addrOfResolver, token.To_SIZE_T()); | ||
| } | ||
| if (reenteredCooperativeGCMode) | ||
| { | ||
| // The prober may have been invalidated by reentering cooperative GC mode, reset it | ||
| BOOL success = lookups->SetUpProber(token.To_SIZE_T(), 0, &probeL); | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| _ASSERTE(success); | ||
| } | ||
| stub = (PCODE) (lookups->Add((size_t)(pLookupHolder->stub()->entryPoint()), &probeL)); | ||
| } | ||
| } | ||
| @@ -1082,7 +1092,20 @@ PCODE VirtualCallStubManager::GetVTableCallStub(DWORD slot) | ||
| { | ||
| if ((stub = (PCODE)(vtableCallers->Find(&probe))) == CALL_STUB_EMPTY_ENTRY) | ||
| { | ||
| VTableCallHolder *pHolder = GenerateVTableCallStub(slot); | ||
| VTableCallHolder *pHolder; | ||
| bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); | ||
| { | ||
| GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); | ||
| pHolder = GenerateVTableCallStub(slot); | ||
| } | ||
| if (reenteredCooperativeGCMode) | ||
| { | ||
| // The prober may have been invalidated by reentering cooperative GC mode, reset it | ||
| BOOL success = vtableCallers->SetUpProber(DispatchToken::CreateDispatchToken(slot).To_SIZE_T(), 0, &probe); | ||
| _ASSERTE(success); | ||
| } | ||
| stub = (PCODE)(vtableCallers->Add((size_t)(pHolder->stub()->entryPoint()), &probe)); | ||
| } | ||
| } | ||
| @@ -1115,9 +1138,7 @@ VTableCallHolder* VirtualCallStubManager::GenerateVTableCallStub(DWORD slot) | ||
| LOG((LF_STUBS, LL_INFO10000, "GenerateVTableCallStub for slot " FMT_ADDR "at" FMT_ADDR "\n", | ||
| DBG_ADDR(slot), DBG_ADDR(pHolder->stub()))); | ||
| #ifdef FEATURE_PERFMAP | ||
| PerfMap::LogStubs(__FUNCTION__, "GenerateVTableCallStub", (PCODE)pHolder->stub(), pHolder->stub()->size(), PerfMapStubType::IndividualWithinBlock); | ||
| #endif | ||
| RETURN(pHolder); | ||
| } | ||
| @@ -2054,14 +2075,24 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, | ||
| } | ||
| #endif // TARGET_X86 && !UNIX_X86_ABI | ||
| pResolveHolder = GenerateResolveStub(pResolverFcn, | ||
| pBackPatchFcn, | ||
| token.To_SIZE_T() | ||
| bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); | ||
| { | ||
| GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); | ||
| pResolveHolder = GenerateResolveStub(pResolverFcn, | ||
| pBackPatchFcn, | ||
| token.To_SIZE_T() | ||
| #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) | ||
| , stackArgumentsSize | ||
| , stackArgumentsSize | ||
| #endif | ||
| ); | ||
| } | ||
| if (reenteredCooperativeGCMode) | ||
| { | ||
| // The prober may have been invalidated by reentering cooperative GC mode, reset it | ||
| BOOL success = resolvers->SetUpProber(token.To_SIZE_T(), 0, &probeR); | ||
| _ASSERTE(success); | ||
| } | ||
| // Add the resolve entrypoint into the cache. | ||
| //@TODO: Can we store a pointer to the holder rather than the entrypoint? | ||
| resolvers->Add((size_t)(pResolveHolder->stub()->resolveEntryPoint()), &probeR); | ||
| @@ -2095,9 +2126,12 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, | ||
| if (addrOfDispatch == CALL_STUB_EMPTY_ENTRY) | ||
| { | ||
| PCODE addrOfFail = pResolveHolder->stub()->failEntryPoint(); | ||
| bool reenteredCooperativeGCMode = false; | ||
| pDispatchHolder = GenerateDispatchStub( | ||
| target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); | ||
| bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); | ||
| { | ||
| GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); | ||
| pDispatchHolder = GenerateDispatchStub( | ||
| target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); | ||
| } | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if (reenteredCooperativeGCMode) | ||
| { | ||
| // The prober may have been invalidated by reentering cooperative GC mode, reset it | ||
| @@ -2208,9 +2242,12 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, | ||
| // so we may have to create it now | ||
| ResolveHolder* pResolveHolder = ResolveHolder::FromResolveEntry(pCallSite->GetSiteTarget()); | ||
| PCODE addrOfFail = pResolveHolder->stub()->failEntryPoint(); | ||
| bool reenteredCooperativeGCMode = false; | ||
| pDispatchHolder = GenerateDispatchStub( | ||
| target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); | ||
| bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); | ||
| { | ||
| GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); | ||
| pDispatchHolder = GenerateDispatchStub( | ||
| target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); | ||
| } | ||
davidwrighton marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if (reenteredCooperativeGCMode) | ||
| { | ||
| // The prober may have been invalidated by reentering cooperative GC mode, reset it | ||
| @@ -2799,7 +2836,6 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStub(PCODE ad | ||
| PRECONDITION(addrOfFail != NULL); | ||
| PRECONDITION(CheckPointer(pMTExpected)); | ||
| PRECONDITION(pMayHaveReenteredCooperativeGCMode != nullptr); | ||
| PRECONDITION(!*pMayHaveReenteredCooperativeGCMode); | ||
| POSTCONDITION(CheckPointer(RETVAL)); | ||
| } CONTRACT_END; | ||
| @@ -2862,9 +2898,7 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStub(PCODE ad | ||
| LOG((LF_STUBS, LL_INFO10000, "GenerateDispatchStub for token" FMT_ADDR "and pMT" FMT_ADDR "at" FMT_ADDR "\n", | ||
| DBG_ADDR(dispatchToken), DBG_ADDR(pMTExpected), DBG_ADDR(holder->stub()))); | ||
| #ifdef FEATURE_PERFMAP | ||
| PerfMap::LogStubs(__FUNCTION__, "GenerateDispatchStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); | ||
| #endif | ||
| RETURN (holder); | ||
| } | ||
| @@ -2888,7 +2922,6 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStubLong(PCODE | ||
| PRECONDITION(addrOfFail != NULL); | ||
| PRECONDITION(CheckPointer(pMTExpected)); | ||
| PRECONDITION(pMayHaveReenteredCooperativeGCMode != nullptr); | ||
| PRECONDITION(!*pMayHaveReenteredCooperativeGCMode); | ||
| POSTCONDITION(CheckPointer(RETVAL)); | ||
| } CONTRACT_END; | ||
| @@ -2923,9 +2956,7 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStubLong(PCODE | ||
| LOG((LF_STUBS, LL_INFO10000, "GenerateDispatchStub for token" FMT_ADDR "and pMT" FMT_ADDR "at" FMT_ADDR "\n", | ||
| DBG_ADDR(dispatchToken), DBG_ADDR(pMTExpected), DBG_ADDR(holder->stub()))); | ||
| #ifdef FEATURE_PERFMAP | ||
| PerfMap::LogStubs(__FUNCTION__, "GenerateDispatchStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); | ||
| #endif | ||
| RETURN (holder); | ||
| } | ||
| @@ -3021,9 +3052,7 @@ ResolveHolder *VirtualCallStubManager::GenerateResolveStub(PCODE addr | ||
| LOG((LF_STUBS, LL_INFO10000, "GenerateResolveStub for token" FMT_ADDR "at" FMT_ADDR "\n", | ||
| DBG_ADDR(dispatchToken), DBG_ADDR(holder->stub()))); | ||
| #ifdef FEATURE_PERFMAP | ||
| PerfMap::LogStubs(__FUNCTION__, "GenerateResolveStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); | ||
| #endif | ||
| RETURN (holder); | ||
| } | ||
| @@ -3054,9 +3083,7 @@ LookupHolder *VirtualCallStubManager::GenerateLookupStub(PCODE addrOfResolver, s | ||
| LOG((LF_STUBS, LL_INFO10000, "GenerateLookupStub for token" FMT_ADDR "at" FMT_ADDR "\n", | ||
| DBG_ADDR(dispatchToken), DBG_ADDR(holder->stub()))); | ||
| #ifdef FEATURE_PERFMAP | ||
| PerfMap::LogStubs(__FUNCTION__, "GenerateLookupStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); | ||
| #endif | ||
| RETURN (holder); | ||
| } | ||
| @@ -3084,8 +3111,12 @@ ResolveCacheElem *VirtualCallStubManager::GenerateResolveCacheElem(void *addrOfC | ||
| CONSISTENCY_CHECK(CheckPointer(pMTExpected)); | ||
| //allocate from the requisite heap and set the appropriate fields | ||
| ResolveCacheElem *e = (ResolveCacheElem*) (void*) | ||
| ResolveCacheElem *e; | ||
| { | ||
| GCX_NOTRIGGER(); | ||
| e = (ResolveCacheElem*) (void*) | ||
| cache_entry_heap->AllocAlignedMem(sizeof(ResolveCacheElem), CODE_SIZE_ALIGN); | ||
| } | ||
| e->pMT = pMTExpected; | ||
| e->token = token; | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.