// This could fail if a different version of dacvars.h or vptr_list.h was used when building
// mscordacwks.dll than when running DacTableGen.
- if (offsetof(DacGlobals, Thread__vtAddr) != header.numGlobals * sizeof(ULONG))
+ if (offsetof(DacGlobals, EEJitManager__vtAddr) != header.numGlobals * sizeof(ULONG))
{
#ifdef _DEBUG
char szMsgBuf[1024];
_snprintf_s(szMsgBuf, sizeof(szMsgBuf), _TRUNCATE,
"DAC fatal error: mismatch in number of globals in DAC table. Read from file: %d, expected: %d.",
header.numGlobals,
- offsetof(DacGlobals, Thread__vtAddr) / sizeof(ULONG));
+ offsetof(DacGlobals, EEJitManager__vtAddr) / sizeof(ULONG));
_ASSERTE_MSG(false, szMsgBuf);
#endif // _DEBUG
_snprintf_s(szMsgBuf, sizeof(szMsgBuf), _TRUNCATE,
"DAC fatal error: mismatch in number of vptrs in DAC table. Read from file: %d, expected: %d.",
header.numVptrs,
- (sizeof(DacGlobals) - offsetof(DacGlobals, Thread__vtAddr)) / sizeof(ULONG));
+ (sizeof(DacGlobals) - offsetof(DacGlobals, EEJitManager__vtAddr)) / sizeof(ULONG));
_ASSERTE_MSG(false, szMsgBuf);
#endif // _DEBUG
{
PWSTR pszRet = NULL;
- ULONG *targ = &g_dacGlobals.Thread__vtAddr;
+ ULONG *targ = &g_dacGlobals.EEJitManager__vtAddr;
ULONG *targStart = targ;
for (ULONG i = 0; i < sizeof(g_dacHostVtPtrs) / sizeof(PVOID); i++)
{
// The host vtable table exactly parallels the
// target vtable table, so just iterate to a match
// return the matching entry.
- host = &g_dacHostVtPtrs.Thread;
- targ = &g_dacGlobals.Thread__vtAddr;
+ host = &g_dacHostVtPtrs.EEJitManager;
+ targ = &g_dacGlobals.EEJitManager__vtAddr;
for (i = 0; i < sizeof(g_dacHostVtPtrs) / sizeof(PVOID); i++)
{
if (*host == vtHost)
// Any class with a vtable that needs to be instantiated
// during debugging data access must be listed here.
-VPTR_CLASS(Thread)
-
VPTR_CLASS(EEJitManager)
#ifdef FEATURE_PREJIT
typedef VPTR(class DebugInfoManager) PTR_DebugInfoManager;
typedef DPTR(class FieldDesc) PTR_FieldDesc;
typedef VPTR(class Frame) PTR_Frame;
-typedef VPTR(class GCFrame) PTR_GCFrame;
+typedef DPTR(class GCFrame) PTR_GCFrame;
typedef VPTR(class ICodeManager) PTR_ICodeManager;
typedef VPTR(class IJitManager) PTR_IJitManager;
typedef DPTR(class InstMethodHashTable) PTR_InstMethodHashTable;
typedef DPTR(class MethodTable) PTR_MethodTable;
typedef VPTR(class Module) PTR_Module;
typedef DPTR(class NDirectMethodDesc) PTR_NDirectMethodDesc;
-typedef VPTR(class Thread) PTR_Thread;
+typedef DPTR(class Thread) PTR_Thread;
typedef DPTR(class Object) PTR_Object;
typedef DPTR(PTR_Object) PTR_PTR_Object;
typedef DPTR(class ObjHeader) PTR_ObjHeader;
typedef VPTR(class DebugInfoManager) PTR_DebugInfoManager;
typedef DPTR(class FieldDesc) PTR_FieldDesc;
typedef VPTR(class Frame) PTR_Frame;
-typedef VPTR(class GCFrame) PTR_GCFrame;
+typedef DPTR(class GCFrame) PTR_GCFrame;
typedef VPTR(class ICodeManager) PTR_ICodeManager;
typedef VPTR(class IJitManager) PTR_IJitManager;
typedef VPTR(struct IUnknown) PTR_IUnknown;
typedef DPTR(class MscorlibBinder) PTR_MscorlibBinder;
typedef VPTR(class Module) PTR_Module;
typedef DPTR(class NDirectMethodDesc) PTR_NDirectMethodDesc;
-typedef VPTR(class Thread) PTR_Thread;
+typedef DPTR(class Thread) PTR_Thread;
typedef DPTR(class Object) PTR_Object;
typedef DPTR(PTR_Object) PTR_PTR_Object;
typedef DPTR(class DelegateObject) PTR_DelegateObject;
bool needReset =
priority != ThreadNative::PRIORITY_NORMAL ||
pThread->HasThreadStateNC(Thread::TSNC_SOWorkNeeded) ||
- !pThread->IsBackground() ||
- pThread->HasCriticalRegion() ||
- pThread->HasThreadAffinity();
+ !pThread->IsBackground();
bool shouldAdjustWorkers = ThreadpoolMgr::ShouldAdjustMaxWorkersActive();
// We now have a Thread object visable to the RS. unmark special status.
hCantStop.Release();
- pThread->SetupThreadForHost();
-
threadHolder.SuppressRelease();
FastInterlockOr((ULONG *) &pThread->m_State, Thread::TS_FullyInitialized);
m_OSThreadId = 0;
m_Priority = INVALID_THREAD_PRIORITY;
m_ExternalRefCount = 1;
- m_UnmanagedRefCount = 0;
m_State = TS_Unstarted;
m_StateNC = TSNC_Unknown;
m_pHelperMethodFrameCallerList = (HelperMethodFrameCallerList*)-1;
#endif
- m_dwHostTaskRefCount = 0;
-
m_pExceptionDuringStartup = NULL;
#ifdef HAVE_GCCOVER
ThrowOutOfMemory();
}
- SetupThreadForHost();
-
-
ThreadStore::TransferStartedThread(this, bRequiresTSL);
#ifdef FEATURE_EVENT_TRACE
{
Thread *next = ThreadStore::GetAllThreadList(thread, 0, 0);
- if (thread->IsDetached() && thread->m_UnmanagedRefCount == 0)
+ if (thread->IsDetached())
{
STRESS_LOG1(LF_SYNC, LL_INFO1000, "T::CDT - detaching thread 0x%p\n", thread);
}
}
-HRESULT Thread::Abort ()
-{
- CONTRACTL
- {
- NOTHROW;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
- }
- CONTRACTL_END;
-
- EX_TRY
- {
- UserAbort(TAR_Thread, EEPolicy::TA_Safe, INFINITE, Thread::UAC_Host);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- return S_OK;
-}
-
-HRESULT Thread::RudeAbort()
-{
- CONTRACTL
- {
- NOTHROW;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
- }
- CONTRACTL_END;
-
- EX_TRY
- {
- UserAbort(TAR_Thread, EEPolicy::TA_Rude, INFINITE, Thread::UAC_Host);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- return S_OK;
-}
-
-HRESULT Thread::NeedsPriorityScheduling(BOOL *pbNeedsPriorityScheduling)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- *pbNeedsPriorityScheduling = (m_fPreemptiveGCDisabled ||
- (g_fEEStarted && this == FinalizerThread::GetFinalizerThread()));
- return S_OK;
-}
-
-
-HRESULT Thread::LocksHeld(SIZE_T *pLockCount)
-{
- LIMITED_METHOD_CONTRACT;
-
- *pLockCount = m_dwLockCount;
- return S_OK;
-}
-
-HRESULT Thread::BeginPreventAsyncAbort()
-{
- WRAPPER_NO_CONTRACT;
-
-#ifdef _DEBUG
- int count =
-#endif
- FastInterlockIncrement((LONG*)&m_PreventAbort);
-
-#ifdef _DEBUG
- ASSERT(count > 0);
-
- FastInterlockIncrement((LONG*)&m_dwDisableAbortCheckCount);
-#endif
-
- return S_OK;
-}
-
-HRESULT Thread::EndPreventAsyncAbort()
-{
- WRAPPER_NO_CONTRACT;
-
-#ifdef _DEBUG
- int count =
-#endif
- FastInterlockDecrement((LONG*)&m_PreventAbort);
-
-#ifdef _DEBUG
- ASSERT(count >= 0);
-
- FastInterlockDecrement((LONG*)&m_dwDisableAbortCheckCount);
-#endif
-
- return S_OK;
-}
-
-
-ULONG Thread::AddRef()
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(m_ExternalRefCount > 0);
-
- _ASSERTE (m_UnmanagedRefCount != (DWORD) -1);
- ULONG ref = FastInterlockIncrement((LONG*)&m_UnmanagedRefCount);
-
- return ref;
-}
-
-ULONG Thread::Release()
-{
- WRAPPER_NO_CONTRACT;
- SUPPORTS_DAC_HOST_ONLY;
-
- _ASSERTE (m_ExternalRefCount > 0);
- _ASSERTE (m_UnmanagedRefCount > 0);
- ULONG ref = FastInterlockDecrement((LONG*)&m_UnmanagedRefCount);
- return ref;
-}
-
-HRESULT Thread::QueryInterface(REFIID riid, void **ppUnk)
-{
- LIMITED_METHOD_CONTRACT;
-
- return E_NOINTERFACE;
-
-}
-
-void Thread::SetupThreadForHost()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- _ASSERTE (GetThread() == this);
-}
-
-
ETaskType GetCurrentTaskType()
{
STATIC_CONTRACT_NOTHROW;
{
WRAPPER_NO_CONTRACT;
- DAC_ENUM_VTHIS();
+ DAC_ENUM_DTHIS();
if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE)
{
if (m_pDomain.IsValid())
// Implementing IUnknown would prevent the field (e.g. m_Context) layout from being rearranged (which will need to be fixed in
// "asmconstants.h" for the respective architecture). As it is, ICLRTask derives from IUnknown and would have got IUnknown implemented
// here - so doing this explicitly and maintaining layout sanity should be just fine.
-class Thread: public IUnknown
+class Thread
{
friend struct ThreadQueue; // used to enqueue & dequeue threads onto SyncBlocks
friend class ThreadStore;
friend class ThreadStatics;
- VPTR_BASE_CONCRETE_VTABLE_CLASS(Thread)
-
public:
enum SetThreadStackGuaranteeScope { STSGuarantee_Force, STSGuarantee_OnlyIfEnabled };
static BOOL IsSetThreadStackGuaranteeInUse(SetThreadStackGuaranteeScope fScope = STSGuarantee_OnlyIfEnabled)
}
public:
+ // Allocator used during marshaling for temporary buffers, much faster than
+ // heap allocation.
+ //
+ // Uses of this allocator should be effectively statically scoped, i.e. a "region"
+ // is started using a CheckPointHolder and GetCheckpoint, and this region can then be used for allocations
+ // from that point onwards, and then all memory is reclaimed when the static scope for the
+ // checkpoint is exited by the running thread.
+ StackingAllocator* m_stackLocalAllocator = NULL;
// If we are trying to suspend a thread, we set the appropriate pending bit to
// indicate why we want to suspend it (TS_GCSuspendPending, TS_UserSuspendPending,
// There are cases during managed debugging when we can run into this situation
};
- // Functions called by host
- STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
- DAC_EMPTY_RET(E_NOINTERFACE);
- STDMETHODIMP_(ULONG) AddRef(void)
- DAC_EMPTY_RET(0);
- STDMETHODIMP_(ULONG) Release(void)
- DAC_EMPTY_RET(0);
- STDMETHODIMP Abort()
- DAC_EMPTY_RET(E_FAIL);
- STDMETHODIMP RudeAbort()
- DAC_EMPTY_RET(E_FAIL);
- STDMETHODIMP NeedsPriorityScheduling(BOOL *pbNeedsPriorityScheduling)
- DAC_EMPTY_RET(E_FAIL);
-
- STDMETHODIMP YieldTask()
- DAC_EMPTY_RET(E_FAIL);
- STDMETHODIMP LocksHeld(SIZE_T *pLockCount)
- DAC_EMPTY_RET(E_FAIL);
-
- STDMETHODIMP BeginPreventAsyncAbort()
- DAC_EMPTY_RET(E_FAIL);
- STDMETHODIMP EndPreventAsyncAbort()
- DAC_EMPTY_RET(E_FAIL);
-
void InternalReset (BOOL fNotFinalizerThread=FALSE, BOOL fThreadObjectResetNeeded=TRUE, BOOL fResetAbort=TRUE);
INT32 ResetManagedThreadObject(INT32 nPriority);
INT32 ResetManagedThreadObjectInCoopMode(INT32 nPriority);
RCWStackHeader* m_pRCWStack;
#endif // FEATURE_COMINTEROP
- // Allocator used during marshaling for temporary buffers, much faster than
- // heap allocation.
- //
- // Uses of this allocator should be effectively statically scoped, i.e. a "region"
- // is started using a CheckPointHolder and GetCheckpoint, and this region can then be used for allocations
- // from that point onwards, and then all memory is reclaimed when the static scope for the
- // checkpoint is exited by the running thread.
- StackingAllocator* m_stackLocalAllocator = NULL;
-
// Flags used to indicate tasks the thread has to do.
ThreadTasks m_ThreadTasks;
return fHasLock;
}
- inline BOOL HasCriticalRegion()
- {
- LIMITED_METHOD_CONTRACT;
- return FALSE;
- }
-
inline DWORD GetNewHashCode()
{
LIMITED_METHOD_CONTRACT;
}
#endif
-public:
-
- BOOL HasThreadAffinity()
- {
- LIMITED_METHOD_CONTRACT;
- return FALSE;
- }
-
private:
LoadLevelLimiter *m_pLoadLimiter;
BOOL InitThread(BOOL fInternal);
BOOL AllocHandles();
- void SetupThreadForHost();
-
//--------------------------------------------------------------
// If the thread was setup through SetupUnstartedThread, rather
// than SetupThread, complete the setup here when the thread is
// Destructor
//--------------------------------------------------------------
#ifndef DACCESS_COMPILE
- virtual ~Thread();
+ ~Thread();
#else
- virtual ~Thread() {}
+ ~Thread() {}
#endif
#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
bool DetectHandleILStubsForDebugger();
- void SetWin32FaultAddress(DWORD eip)
- {
- LIMITED_METHOD_CONTRACT;
- m_Win32FaultAddress = eip;
- }
-
- void SetWin32FaultCode(DWORD code)
- {
- LIMITED_METHOD_CONTRACT;
- m_Win32FaultCode = code;
- }
-
- DWORD GetWin32FaultAddress()
- {
- LIMITED_METHOD_CONTRACT;
- return m_Win32FaultAddress;
- }
-
- DWORD GetWin32FaultCode()
- {
- LIMITED_METHOD_CONTRACT;
- return m_Win32FaultCode;
- }
-
#ifdef ENABLE_CONTRACTS
ClrDebugState *GetClrDebugState()
{
#endif // FEATURE_HIJACK
- DWORD m_Win32FaultAddress;
- DWORD m_Win32FaultCode;
-
// Support for Wait/Notify
BOOL Block(INT32 timeOut, PendingSync *syncInfo);
void Wake(SyncBlock *psb);
ULONG m_ExternalRefCount;
- ULONG m_UnmanagedRefCount;
-
LONG m_TraceCallCount;
private:
#endif // _DEBUG
private:
- LONG m_dwHostTaskRefCount;
-
-private:
// If HasStarted fails, we cache the exception here, and rethrow on the thread which
// calls Thread.Start.
Exception* m_pExceptionDuringStartup;