Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 58f6883

Browse files
authored
1 parent 192be6d commit 58f6883

File tree

3 files changed

+180
-141
lines changed

3 files changed

+180
-141
lines changed

src/vm/threads.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@
5757
uint64_t Thread::dead_threads_non_alloc_bytes = 0;
5858

5959
SPTR_IMPL(ThreadStore, ThreadStore, s_pThreadStore);
60-
CONTEXT *ThreadStore::s_pOSContext = NULL;
60+
61+
CONTEXT* ThreadStore::s_pOSContext = NULL;
62+
BYTE* ThreadStore::s_pOSContextBuffer = NULL;
63+
6164
CLREvent *ThreadStore::s_pWaitForStackCrawlEvent;
6265

6366
PTR_ThreadLocalModule ThreadLocalBlock::GetTLMIfExists(ModuleIndex index)
@@ -1452,7 +1455,6 @@ Thread::Thread()
14521455
m_fHasDeadThreadBeenConsideredForGCTrigger = false;
14531456
m_TraceCallCount = 0;
14541457
m_ThrewControlForThread = 0;
1455-
m_OSContext = NULL;
14561458
m_ThreadTasks = (ThreadTasks)0;
14571459
m_pLoadLimiter= NULL;
14581460
m_pLoadingFile = NULL;
@@ -1487,7 +1489,11 @@ Thread::Thread()
14871489
NewHolder<CONTEXT> contextHolder(m_OSContext);
14881490

14891491
m_pSavedRedirectContext = NULL;
1490-
NewHolder<CONTEXT> savedRedirectContextHolder(m_pSavedRedirectContext);
1492+
m_pOSContextBuffer = NULL;
1493+
1494+
#ifdef _DEBUG
1495+
m_RedirectContextInUse = false;
1496+
#endif
14911497

14921498
#ifdef FEATURE_COMINTEROP
14931499
m_pRCWStack = new RCWStackHeader();
@@ -1563,7 +1569,6 @@ Thread::Thread()
15631569
trackSyncHolder.SuppressRelease();
15641570
#endif
15651571
contextHolder.SuppressRelease();
1566-
savedRedirectContextHolder.SuppressRelease();
15671572

15681573
#ifdef FEATURE_COMINTEROP
15691574
m_uliInitializeSpyCookie.QuadPart = 0ul;
@@ -2640,11 +2645,18 @@ Thread::~Thread()
26402645
if (m_OSContext)
26412646
delete m_OSContext;
26422647

2643-
if (GetSavedRedirectContext())
2648+
if (m_pOSContextBuffer)
26442649
{
2645-
delete GetSavedRedirectContext();
2646-
SetSavedRedirectContext(NULL);
2650+
delete[] m_pOSContextBuffer;
2651+
m_pOSContextBuffer = NULL;
26472652
}
2653+
else if (m_pSavedRedirectContext)
2654+
{
2655+
delete m_pSavedRedirectContext;
2656+
}
2657+
2658+
MarkRedirectContextInUse(m_pSavedRedirectContext);
2659+
m_pSavedRedirectContext = NULL;
26482660

26492661
#ifdef FEATURE_COMINTEROP
26502662
if (m_pRCWStack)

src/vm/threads.h

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4339,8 +4339,21 @@ class Thread: public IUnknown
43394339
#endif // _DEBUG
43404340

43414341
private:
4342+
// context used during redirection of this thread
4343+
// NOTE: there is only one. Since redirection cannot be nested
4344+
// if more than one are needed, something is wrong.
43424345
PTR_CONTEXT m_pSavedRedirectContext;
43434346

4347+
// in a case when we need the redirection context to include CONTEXT_XSTATE
4348+
// this is the buffer that contains the context parts.
4349+
// we need the buffer so we could deallocate the whole deal.
4350+
BYTE* m_pOSContextBuffer;
4351+
4352+
#ifdef _DEBUG
4353+
// validate that we use only one context per thread.
4354+
bool m_RedirectContextInUse;
4355+
#endif
4356+
43444357
BOOL IsContextSafeToRedirect(T_CONTEXT* pContext);
43454358

43464359
public:
@@ -4351,14 +4364,26 @@ class Thread: public IUnknown
43514364
}
43524365

43534366
#ifndef DACCESS_COMPILE
4354-
void SetSavedRedirectContext(PT_CONTEXT pCtx)
4367+
void MarkRedirectContextInUse(PTR_CONTEXT pCtx)
43554368
{
43564369
LIMITED_METHOD_CONTRACT;
4357-
m_pSavedRedirectContext = pCtx;
4358-
}
4370+
#ifdef _DEBUG
4371+
_ASSERTE(!m_RedirectContextInUse);
4372+
_ASSERTE(pCtx == m_pSavedRedirectContext);
4373+
m_RedirectContextInUse = true;
43594374
#endif
4375+
}
43604376

4361-
void EnsurePreallocatedContext();
4377+
void UnmarkRedirectContextInUse(PTR_CONTEXT pCtx)
4378+
{
4379+
LIMITED_METHOD_CONTRACT;
4380+
#ifdef _DEBUG
4381+
_ASSERTE(m_RedirectContextInUse);
4382+
_ASSERTE(pCtx == m_pSavedRedirectContext);
4383+
m_RedirectContextInUse = false;
4384+
#endif
4385+
}
4386+
#endif //DACCESS_COMPILE
43624387

43634388
ThreadLocalBlock m_ThreadLocalBlock;
43644389

@@ -5290,12 +5315,21 @@ class ThreadStore
52905315

52915316
#endif
52925317
private:
5318+
static BYTE* s_pOSContextBuffer;
52935319
static CONTEXT *s_pOSContext;
52945320
public:
5295-
// We can not do any memory allocation after we suspend a thread in order ot
5296-
// avoid deadlock situation.
5321+
// Pre-allocate an OS context for possible use by a redirected thread and keep in a static variable.
5322+
//
5323+
// There are two reasons for this pattern:
5324+
// - We can not do any memory allocation after we suspend a thread in order to avoid deadlock situation.
5325+
// So, when anticipating a need, we must pre-allocate.
5326+
//
5327+
// - Even though we know the thread we are suspending, we do not want to put the context directly on the
5328+
// thread because the thread only _may_ need the context. Often it does not end up needing it,
5329+
// then we will keep the context for the next time like this.
52975330
static void AllocateOSContext();
5298-
static CONTEXT *GrabOSContext();
5331+
// Retrieves and detaches the pre-alocated context + optional containing buffer (when CONTEXT_XSTATE is used)
5332+
static CONTEXT* GrabOSContext(BYTE** contextBuffer);
52995333

53005334
private:
53015335
// Thread abort needs to walk stack to decide if thread abort can proceed.

0 commit comments

Comments
 (0)