Skip to content

Commit 050c506

Browse files
authored
Remove thread pointer from AwareLock (#112715)
1 parent 9ccb9de commit 050c506

File tree

4 files changed

+33
-53
lines changed

4 files changed

+33
-53
lines changed

src/coreclr/vm/syncblk.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,23 +1815,20 @@ BOOL ObjHeader::GetThreadOwningMonitorLock(DWORD *pThreadId, DWORD *pAcquisition
18151815
SyncBlock* psb = g_pSyncTable[(int)index].m_SyncBlock;
18161816

18171817
_ASSERTE(psb->GetMonitor() != NULL);
1818-
Thread* pThread = psb->GetMonitor()->GetHoldingThread();
1819-
// If the lock is orphaned during sync block creation, pThread would be assigned -1.
1820-
// Otherwise pThread would point to the owning thread if there was one or NULL if there wasn't.
1821-
if (pThread == NULL || pThread == (Thread*) -1)
1818+
DWORD holdingThreadId = psb->GetMonitor()->GetHoldingThreadId();
1819+
// If the lock is orphaned during sync block creation, holdingThreadId would be assigned -1.
1820+
// Otherwise it would be the id of the holding thread if there is one or 0 if there isn't.
1821+
if (holdingThreadId == 0 || holdingThreadId == (DWORD)-1)
18221822
{
18231823
*pThreadId = 0;
18241824
*pAcquisitionCount = 0;
18251825
return FALSE;
18261826
}
18271827
else
18281828
{
1829-
// However, the lock might get orphaned after the sync block is created.
1830-
// Therefore accessing pThread is not safe and pThread->GetThreadId() shouldn't be used.
1831-
// The thread id can be obtained from the monitor, which would be the id of the thread that owned the lock.
1832-
// Notice this id now could have been reused for a different thread,
1833-
// but this way we avoid crashing the process and orphaned locks shouldn't be expected to work correctly anyway.
1834-
*pThreadId = psb->GetMonitor()->GetHoldingThreadId();
1829+
// Notice this id now could have been reused for a different thread (in case the lock was orphaned),
1830+
// but orphaned locks shouldn't be expected to work correctly anyway.
1831+
*pThreadId = holdingThreadId;
18351832
*pAcquisitionCount = psb->GetMonitor()->GetRecursionLevel();
18361833
return TRUE;
18371834
}
@@ -2203,7 +2200,6 @@ SyncBlock *ObjHeader::GetSyncBlock()
22032200
if (pThread == NULL)
22042201
{
22052202
// The lock is orphaned.
2206-
pThread = (Thread*) -1;
22072203
threadId = -1;
22082204
osThreadId = (SIZE_T)-1;
22092205
}
@@ -2213,7 +2209,7 @@ SyncBlock *ObjHeader::GetSyncBlock()
22132209
osThreadId = pThread->GetOSThreadId64();
22142210
}
22152211

2216-
syncBlock->InitState(recursionLevel + 1, pThread, threadId, osThreadId);
2212+
syncBlock->InitState(recursionLevel + 1, threadId, osThreadId);
22172213
}
22182214
}
22192215
else if ((bits & BIT_SBLK_IS_HASHCODE) != 0)
@@ -2334,6 +2330,17 @@ void ObjHeader::PulseAll()
23342330
//
23352331
// ***************************************************************************
23362332

2333+
#endif // !DACCESS_COMPILE
2334+
2335+
// the DAC needs to have this method available
2336+
PTR_Thread AwareLock::GetHoldingThread()
2337+
{
2338+
LIMITED_METHOD_CONTRACT;
2339+
return g_pThinLockThreadIdDispenser->IdToThreadWithValidation(m_HoldingThreadId);
2340+
}
2341+
2342+
#ifndef DACCESS_COMPILE
2343+
23372344
void AwareLock::AllocLockSemEvent()
23382345
{
23392346
CONTRACTL
@@ -2371,12 +2378,11 @@ void AwareLock::Enter()
23712378

23722379
Thread *pCurThread = GetThread();
23732380
LockState state = m_lockState.VolatileLoadWithoutBarrier();
2374-
if (!state.IsLocked() || m_HoldingThread != pCurThread)
2381+
if (!state.IsLocked() || m_HoldingThreadId != pCurThread->GetThreadId())
23752382
{
23762383
if (m_lockState.InterlockedTryLock_Or_RegisterWaiter(this, state))
23772384
{
23782385
// We get here if we successfully acquired the mutex.
2379-
m_HoldingThread = pCurThread;
23802386
m_HoldingThreadId = pCurThread->GetThreadId();
23812387
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
23822388
m_Recursion = 1;
@@ -2433,14 +2439,13 @@ BOOL AwareLock::TryEnter(INT32 timeOut)
24332439
}
24342440

24352441
LockState state = m_lockState.VolatileLoadWithoutBarrier();
2436-
if (!state.IsLocked() || m_HoldingThread != pCurThread)
2442+
if (!state.IsLocked() || m_HoldingThreadId != pCurThread->GetThreadId())
24372443
{
24382444
if (timeOut == 0
24392445
? m_lockState.InterlockedTryLock(state)
24402446
: m_lockState.InterlockedTryLock_Or_RegisterWaiter(this, state))
24412447
{
24422448
// We get here if we successfully acquired the mutex.
2443-
m_HoldingThread = pCurThread;
24442449
m_HoldingThreadId = pCurThread->GetThreadId();
24452450
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
24462451
m_Recursion = 1;
@@ -2720,7 +2725,6 @@ BOOL AwareLock::EnterEpilogHelper(Thread* pCurThread, INT32 timeOut)
27202725
return false;
27212726
}
27222727

2723-
m_HoldingThread = pCurThread;
27242728
m_HoldingThreadId = pCurThread->GetThreadId();
27252729
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
27262730
m_Recursion = 1;
@@ -2783,7 +2787,7 @@ LONG AwareLock::LeaveCompletely()
27832787
BOOL AwareLock::OwnedByCurrentThread()
27842788
{
27852789
WRAPPER_NO_CONTRACT;
2786-
return (GetThread() == m_HoldingThread);
2790+
return (GetThread()->GetThreadId() == m_HoldingThreadId);
27872791
}
27882792

27892793
// ***************************************************************************

src/coreclr/vm/syncblk.h

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,6 @@ class AwareLock
435435
LockState m_lockState;
436436

437437
ULONG m_Recursion;
438-
PTR_Thread m_HoldingThread;
439438
DWORD m_HoldingThreadId;
440439
SIZE_T m_HoldingOSThreadId;
441440

@@ -456,10 +455,6 @@ class AwareLock
456455
// Only SyncBlocks can create AwareLocks. Hence this private constructor.
457456
AwareLock(DWORD indx)
458457
: m_Recursion(0),
459-
#ifndef DACCESS_COMPILE
460-
// PreFAST has trouble with initializing a NULL PTR_Thread.
461-
m_HoldingThread(NULL),
462-
#endif // DACCESS_COMPILE
463458
m_HoldingThreadId(0),
464459
m_HoldingOSThreadId(0),
465460
m_TransientPrecious(0),
@@ -519,12 +514,6 @@ class AwareLock
519514
return m_Recursion;
520515
}
521516

522-
PTR_Thread GetHoldingThread() const
523-
{
524-
LIMITED_METHOD_CONTRACT;
525-
return m_HoldingThread;
526-
}
527-
528517
DWORD GetHoldingThreadId() const
529518
{
530519
LIMITED_METHOD_CONTRACT;
@@ -537,13 +526,12 @@ class AwareLock
537526
bool ShouldStopPreemptingWaiters() const;
538527

539528
private: // friend access is required for this unsafe function
540-
void InitializeToLockedWithNoWaiters(ULONG recursionLevel, PTR_Thread holdingThread, DWORD holdingThreadId, SIZE_T holdingOSThreadId)
529+
void InitializeToLockedWithNoWaiters(ULONG recursionLevel, DWORD holdingThreadId, SIZE_T holdingOSThreadId)
541530
{
542531
WRAPPER_NO_CONTRACT;
543532

544533
m_lockState.InitializeToLockedWithNoWaiters();
545534
m_Recursion = recursionLevel;
546-
m_HoldingThread = holdingThread;
547535
m_HoldingThreadId = holdingThreadId;
548536
m_HoldingOSThreadId = holdingOSThreadId;
549537
}
@@ -581,6 +569,7 @@ class AwareLock
581569
void AllocLockSemEvent();
582570
LONG LeaveCompletely();
583571
BOOL OwnedByCurrentThread();
572+
PTR_Thread GetHoldingThread();
584573

585574
void IncrementTransientPrecious()
586575
{
@@ -604,14 +593,6 @@ class AwareLock
604593
// protect it.
605594
inline OBJECTREF GetOwningObject();
606595

607-
// Provide access to the Thread object that owns this awarelock. This is used
608-
// to provide a host to find out owner of a lock.
609-
inline PTR_Thread GetOwningThread()
610-
{
611-
LIMITED_METHOD_CONTRACT;
612-
return m_HoldingThread;
613-
}
614-
615596
static int GetOffsetOfHoldingOSThreadId()
616597
{
617598
LIMITED_METHOD_CONTRACT;
@@ -1279,10 +1260,10 @@ class SyncBlock
12791260
// This should ONLY be called when initializing a SyncBlock (i.e. ONLY from
12801261
// ObjHeader::GetSyncBlock()), otherwise we'll have a race condition.
12811262
// </NOTE>
1282-
void InitState(ULONG recursionLevel, PTR_Thread holdingThread, DWORD holdingThreadId, SIZE_T holdingOSThreadId)
1263+
void InitState(ULONG recursionLevel, DWORD holdingThreadId, SIZE_T holdingOSThreadId)
12831264
{
12841265
WRAPPER_NO_CONTRACT;
1285-
m_Monitor.InitializeToLockedWithNoWaiters(recursionLevel, holdingThread, holdingThreadId, holdingOSThreadId);
1266+
m_Monitor.InitializeToLockedWithNoWaiters(recursionLevel, holdingThreadId, holdingOSThreadId);
12861267
}
12871268

12881269
#if defined(ENABLE_CONTRACTS_IMPL)

src/coreclr/vm/syncblk.inl

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,13 @@ FORCEINLINE bool AwareLock::TryEnterHelper(Thread* pCurThread)
478478

479479
if (m_lockState.InterlockedTryLock())
480480
{
481-
m_HoldingThread = pCurThread;
482481
m_HoldingThreadId = pCurThread->GetThreadId();
483482
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
484483
m_Recursion = 1;
485484
return true;
486485
}
487486

488-
if (GetOwningThread() == pCurThread) /* monitor is held, but it could be a recursive case */
487+
if (GetHoldingThreadId() == pCurThread->GetThreadId()) /* monitor is held, but it could be a recursive case */
489488
{
490489
m_Recursion++;
491490
return true;
@@ -505,7 +504,7 @@ FORCEINLINE AwareLock::EnterHelperResult AwareLock::TryEnterBeforeSpinLoopHelper
505504

506505
// Check the recursive case once before the spin loop. If it's not the recursive case in the beginning, it will not
507506
// be in the future, so the spin loop can avoid checking the recursive case.
508-
if (!state.IsLocked() || GetOwningThread() != pCurThread)
507+
if (!state.IsLocked() || GetHoldingThreadId() != pCurThread->GetThreadId())
509508
{
510509
if (m_lockState.InterlockedTrySetShouldNotPreemptWaitersIfNecessary(this, state))
511510
{
@@ -525,7 +524,6 @@ FORCEINLINE AwareLock::EnterHelperResult AwareLock::TryEnterBeforeSpinLoopHelper
525524
}
526525

527526
// Lock was acquired and the spinner was not registered
528-
m_HoldingThread = pCurThread;
529527
m_HoldingThreadId = pCurThread->GetThreadId();
530528
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
531529
m_Recursion = 1;
@@ -558,7 +556,6 @@ FORCEINLINE AwareLock::EnterHelperResult AwareLock::TryEnterInsideSpinLoopHelper
558556
}
559557

560558
// Lock was acquired and spinner was unregistered
561-
m_HoldingThread = pCurThread;
562559
m_HoldingThreadId = pCurThread->GetThreadId();
563560
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
564561
m_Recursion = 1;
@@ -582,7 +579,6 @@ FORCEINLINE bool AwareLock::TryEnterAfterSpinLoopHelper(Thread *pCurThread)
582579
}
583580

584581
// Spinner was unregistered and the lock was acquired
585-
m_HoldingThread = pCurThread;
586582
m_HoldingThreadId = pCurThread->GetThreadId();
587583
m_HoldingOSThreadId = pCurThread->GetOSThreadId64();
588584
m_Recursion = 1;
@@ -687,7 +683,7 @@ FORCEINLINE AwareLock::LeaveHelperAction AwareLock::LeaveHelper(Thread* pCurThre
687683
MODE_ANY;
688684
} CONTRACTL_END;
689685

690-
if (m_HoldingThread != pCurThread)
686+
if (m_HoldingThreadId != pCurThread->GetThreadId())
691687
return AwareLock::LeaveHelperAction_Error;
692688

693689
_ASSERTE(m_lockState.VolatileLoadWithoutBarrier().IsLocked());
@@ -702,7 +698,6 @@ FORCEINLINE AwareLock::LeaveHelperAction AwareLock::LeaveHelper(Thread* pCurThre
702698

703699
if (--m_Recursion == 0)
704700
{
705-
m_HoldingThread = NULL;
706701
m_HoldingThreadId = 0;
707702
m_HoldingOSThreadId = 0;
708703

src/coreclr/vm/threads.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4428,19 +4428,19 @@ class IdDispenser
44284428
return result;
44294429
}
44304430

4431-
Thread *IdToThreadWithValidation(DWORD id)
4431+
PTR_Thread IdToThreadWithValidation(DWORD id)
44324432
{
44334433
WRAPPER_NO_CONTRACT;
44344434

44354435
CrstHolder ch(&m_Crst);
44364436

4437-
Thread *result = NULL;
4437+
PTR_Thread result = NULL;
44384438
if (id <= m_highestId)
44394439
result = m_idToThread[id];
44404440
// m_idToThread may have Thread*, or the next free slot
4441-
if ((size_t)result <= m_idToThreadCapacity)
4441+
if (dac_cast<size_t>(result) <= m_idToThreadCapacity)
44424442
result = NULL;
4443-
_ASSERTE(result == NULL || ((size_t)result & 0x3) == 0 || ((Thread*)result)->GetThreadId() == id);
4443+
_ASSERTE(result == NULL || (dac_cast<size_t>(result) & 0x3) == 0 || ((Thread*)result)->GetThreadId() == id);
44444444
return result;
44454445
}
44464446
};

0 commit comments

Comments
 (0)