diff options
-rw-r--r-- | src/inc/corerror.xml | 5 | ||||
-rw-r--r-- | src/inc/corprof.idl | 6 | ||||
-rw-r--r-- | src/inc/profilepriv.h | 2 | ||||
-rw-r--r-- | src/inc/profilepriv.inl | 2 | ||||
-rw-r--r-- | src/pal/prebuilt/inc/corerror.h | 1 | ||||
-rw-r--r-- | src/pal/prebuilt/inc/corprof.h | 16 | ||||
-rw-r--r-- | src/vm/profilingenumerators.cpp | 5 | ||||
-rw-r--r-- | src/vm/proftoeeinterfaceimpl.cpp | 80 | ||||
-rw-r--r-- | src/vm/proftoeeinterfaceimpl.h | 4 | ||||
-rw-r--r-- | src/vm/threadsuspend.h | 3 |
10 files changed, 109 insertions, 15 deletions
diff --git a/src/inc/corerror.xml b/src/inc/corerror.xml index 994195f27e..d8b8f6361e 100644 --- a/src/inc/corerror.xml +++ b/src/inc/corerror.xml @@ -1285,6 +1285,11 @@ <Comment> An unknown error occurred in the Diagnpostics IPC Server. </Comment> </HRESULT> +<HRESULT NumericValue="0x80131388"> + <SymbolicName>CORPROF_E_SUSPENSION_IN_PROGRESS</SymbolicName> + <Comment> The runtime cannot be suspened since a suspension is already in progress. </Comment> +</HRESULT> + <HRESULT NumericValue="0x80131401"> <SymbolicName>SECURITY_E_INCOMPATIBLE_SHARE</SymbolicName> <Message>"Loading this assembly would produce a different grant set from other instances."</Message> diff --git a/src/inc/corprof.idl b/src/inc/corprof.idl index f5ad6b5120..1d66137b10 100644 --- a/src/inc/corprof.idl +++ b/src/inc/corprof.idl @@ -3974,6 +3974,12 @@ interface ICorProfilerInfo10 : ICorProfilerInfo9 [in] ULONG cFunctions, [in, size_is(cFunctions)] ModuleID moduleIds[], [in, size_is(cFunctions)] mdMethodDef methodIds[]); + + // Suspend the runtime without performing a GC. + HRESULT SuspendRuntime(); + + // Restart the runtime from a previous suspension. + HRESULT ResumeRuntime(); } /* diff --git a/src/inc/profilepriv.h b/src/inc/profilepriv.h index 647457e932..a5e23987d2 100644 --- a/src/inc/profilepriv.h +++ b/src/inc/profilepriv.h @@ -117,6 +117,8 @@ struct ProfControlBlock BOOL fConcurrentGCDisabledForAttach; Volatile<BOOL> fProfControlBlockInitialized; + + Volatile<BOOL> fProfilerRequestedRuntimeSuspend; void Init(); void ResetPerSessionStatus(); diff --git a/src/inc/profilepriv.inl b/src/inc/profilepriv.inl index 5a04bd3302..5a0513f4a3 100644 --- a/src/inc/profilepriv.inl +++ b/src/inc/profilepriv.inl @@ -72,6 +72,8 @@ inline void ProfControlBlock::Init() ResetPerSessionStatus(); fProfControlBlockInitialized = TRUE; + + fProfilerRequestedRuntimeSuspend = FALSE; } // Reset those variables that is only for the current attach session diff --git a/src/pal/prebuilt/inc/corerror.h b/src/pal/prebuilt/inc/corerror.h index 3d92d63fd7..7bd0c10221 100644 --- a/src/pal/prebuilt/inc/corerror.h +++ b/src/pal/prebuilt/inc/corerror.h @@ -232,6 +232,7 @@ #define CORDIAGIPC_E_UNKNOWN_COMMAND EMAKEHR(0x1385) #define CORDIAGIPC_E_UNKNOWN_MAGIC EMAKEHR(0x1386) #define CORDIAGIPC_E_UNKNOWN_ERROR EMAKEHR(0x1387) +#define CORPROF_E_SUSPENSION_IN_PROGRESS EMAKEHR(0x1388) #define SECURITY_E_INCOMPATIBLE_SHARE EMAKEHR(0x1401) #define SECURITY_E_UNVERIFIABLE EMAKEHR(0x1402) #define SECURITY_E_INCOMPATIBLE_EVIDENCE EMAKEHR(0x1403) diff --git a/src/pal/prebuilt/inc/corprof.h b/src/pal/prebuilt/inc/corprof.h index be4b8102eb..2717067ed3 100644 --- a/src/pal/prebuilt/inc/corprof.h +++ b/src/pal/prebuilt/inc/corprof.h @@ -15208,6 +15208,10 @@ EXTERN_C const IID IID_ICorProfilerInfo10; /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; + virtual HRESULT STDMETHODCALLTYPE SuspendRuntime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResumeRuntime( void) = 0; + }; @@ -15815,6 +15819,12 @@ EXTERN_C const IID IID_ICorProfilerInfo10; /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); + HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( + ICorProfilerInfo10 * This); + + HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( + ICorProfilerInfo10 * This); + END_INTERFACE } ICorProfilerInfo10Vtbl; @@ -16129,6 +16139,12 @@ EXTERN_C const IID IID_ICorProfilerInfo10; #define ICorProfilerInfo10_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) +#define ICorProfilerInfo10_SuspendRuntime(This) \ + ( (This)->lpVtbl -> SuspendRuntime(This) ) + +#define ICorProfilerInfo10_ResumeRuntime(This) \ + ( (This)->lpVtbl -> ResumeRuntime(This) ) + #endif /* COBJMACROS */ diff --git a/src/vm/profilingenumerators.cpp b/src/vm/profilingenumerators.cpp index b03638ffd0..d5836106cb 100644 --- a/src/vm/profilingenumerators.cpp +++ b/src/vm/profilingenumerators.cpp @@ -523,7 +523,9 @@ HRESULT ProfilerThreadEnum::Init() } CONTRACTL_END; - ThreadStoreLockHolder tsLock; + // If a profiler has requested that the runtime suspend to do stack snapshots, it + // will be holding the ThreadStore lock already + ThreadStoreLockHolder tsLock(!g_profControlBlock.fProfilerRequestedRuntimeSuspend); Thread * pThread = NULL; @@ -546,6 +548,7 @@ HRESULT ProfilerThreadEnum::Init() *m_elements.Append() = (ThreadID) pThread; } + _ASSERTE(ThreadStore::HoldingThreadStore() || g_profControlBlock.fProfilerRequestedRuntimeSuspend); return S_OK; } diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 4d9b733856..13bf2a4b4b 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -6938,6 +6938,71 @@ HRESULT ProfToEEInterfaceImpl::GetLOHObjectSizeThreshold(DWORD *pThreshold) return S_OK; } +HRESULT ProfToEEInterfaceImpl::SuspendRuntime() +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_ANY; + CAN_TAKE_LOCK; + EE_THREAD_NOT_REQUIRED; + } + CONTRACTL_END; + + PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX( + kP2EEAllowableAfterAttach | kP2EETriggers, + (LF_CORPROF, + LL_INFO1000, + "**PROF: SuspendRuntime\n")); + + if (!g_fEEStarted) + { + return CORPROF_E_RUNTIME_UNINITIALIZED; + } + + if (ThreadSuspend::SysIsSuspendInProgress() || (ThreadSuspend::GetSuspensionThread() != 0)) + { + return CORPROF_E_SUSPENSION_IN_PROGRESS; + } + + g_profControlBlock.fProfilerRequestedRuntimeSuspend = TRUE; + ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_REASON::SUSPEND_FOR_PROFILER); + return S_OK; +} + +HRESULT ProfToEEInterfaceImpl::ResumeRuntime() +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX( + kP2EEAllowableAfterAttach | kP2EETriggers, + (LF_CORPROF, + LL_INFO1000, + "**PROF: ResumeRuntime\n")); + + if (!g_fEEStarted) + { + return CORPROF_E_RUNTIME_UNINITIALIZED; + } + + if (!g_profControlBlock.fProfilerRequestedRuntimeSuspend) + { + return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE; + } + + ThreadSuspend::RestartEE(FALSE /* bFinishedGC */, TRUE /* SuspendSucceeded */); + g_profControlBlock.fProfilerRequestedRuntimeSuspend = FALSE; + return S_OK; +} + /* * GetStringLayout * @@ -7796,15 +7861,6 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, BYTE * pbContext, ULONG32 contextSize) { - -#if !defined(FEATURE_HIJACK) - - // DoStackSnapshot needs Thread::Suspend/ResumeThread functionality. - // On platforms w/o support for these APIs return E_NOTIMPL. - return E_NOTIMPL; - -#else // !defined(FEATURE_HIJACK) - CONTRACTL { // Yay! (Note: NOTHROW is vital. The throw at minimum allocates @@ -7968,7 +8024,7 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, HostCallPreference hostCallPreference; // First, check "1) Target thread to walk == current thread OR Target thread is suspended" - if (pThreadToSnapshot != pCurrentThread) + if (pThreadToSnapshot != pCurrentThread && !g_profControlBlock.fProfilerRequestedRuntimeSuspend) { #ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND hr = E_NOTIMPL; @@ -8151,7 +8207,7 @@ HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread, // inlined P/Invoke. In this case, the InlinedCallFrame will be used to help start off our // stackwalk at the top of the stack. // - if (pThreadToSnapshot != pCurrentThread) + if (pThreadToSnapshot != pCurrentThread && !g_profControlBlock.fProfilerRequestedRuntimeSuspend) { #ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND hr = E_NOTIMPL; @@ -8253,8 +8309,6 @@ Cleanup: } return hr; - -#endif // !defined(FEATURE_HIJACK) } diff --git a/src/vm/proftoeeinterfaceimpl.h b/src/vm/proftoeeinterfaceimpl.h index c6dc289037..016b1f714b 100644 --- a/src/vm/proftoeeinterfaceimpl.h +++ b/src/vm/proftoeeinterfaceimpl.h @@ -615,6 +615,10 @@ public: ModuleID moduleIds[], mdMethodDef methodIds[]); + COM_METHOD SuspendRuntime(); + + COM_METHOD ResumeRuntime(); + // end ICorProfilerInfo10 protected: diff --git a/src/vm/threadsuspend.h b/src/vm/threadsuspend.h index 44ccce56a0..a5fb30238d 100644 --- a/src/vm/threadsuspend.h +++ b/src/vm/threadsuspend.h @@ -183,7 +183,8 @@ public: SUSPEND_FOR_SHUTDOWN = 4, SUSPEND_FOR_DEBUGGER = 5, SUSPEND_FOR_GC_PREP = 6, - SUSPEND_FOR_DEBUGGER_SWEEP = 7 // This must only be used in Thread::SysSweepThreadsForDebug + SUSPEND_FOR_DEBUGGER_SWEEP = 7, // This must only be used in Thread::SysSweepThreadsForDebug + SUSPEND_FOR_PROFILER = 8 } SUSPEND_REASON; private: |