summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inc/corerror.xml5
-rw-r--r--src/inc/corprof.idl6
-rw-r--r--src/inc/profilepriv.h2
-rw-r--r--src/inc/profilepriv.inl2
-rw-r--r--src/pal/prebuilt/inc/corerror.h1
-rw-r--r--src/pal/prebuilt/inc/corprof.h16
-rw-r--r--src/vm/profilingenumerators.cpp5
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp80
-rw-r--r--src/vm/proftoeeinterfaceimpl.h4
-rw-r--r--src/vm/threadsuspend.h3
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: