@@ -4339,8 +4339,21 @@ class Thread: public IUnknown
4339
4339
#endif // _DEBUG
4340
4340
4341
4341
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.
4342
4345
PTR_CONTEXT m_pSavedRedirectContext;
4343
4346
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
+
4344
4357
BOOL IsContextSafeToRedirect (T_CONTEXT* pContext);
4345
4358
4346
4359
public:
@@ -4351,14 +4364,26 @@ class Thread: public IUnknown
4351
4364
}
4352
4365
4353
4366
#ifndef DACCESS_COMPILE
4354
- void SetSavedRedirectContext (PT_CONTEXT pCtx)
4367
+ void MarkRedirectContextInUse (PTR_CONTEXT pCtx)
4355
4368
{
4356
4369
LIMITED_METHOD_CONTRACT;
4357
- m_pSavedRedirectContext = pCtx;
4358
- }
4370
+ #ifdef _DEBUG
4371
+ _ASSERTE (!m_RedirectContextInUse);
4372
+ _ASSERTE (pCtx == m_pSavedRedirectContext);
4373
+ m_RedirectContextInUse = true ;
4359
4374
#endif
4375
+ }
4360
4376
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
4362
4387
4363
4388
ThreadLocalBlock m_ThreadLocalBlock;
4364
4389
@@ -5290,12 +5315,21 @@ class ThreadStore
5290
5315
5291
5316
#endif
5292
5317
private:
5318
+ static BYTE* s_pOSContextBuffer;
5293
5319
static CONTEXT *s_pOSContext;
5294
5320
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.
5297
5330
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);
5299
5333
5300
5334
private:
5301
5335
// Thread abort needs to walk stack to decide if thread abort can proceed.
0 commit comments