pThread->HasCriticalRegion() ||
pThread->HasThreadAffinity();
+ // Read fenced call
bool shouldAdjustWorkers = ThreadpoolMgr::ShouldAdjustMaxWorkersActive();
//
{
HELPER_METHOD_FRAME_BEGIN_RET_0();
+ if (needReset)
+ pThread->InternalReset(FALSE, TRUE, TRUE, FALSE);
+
if (shouldAdjustWorkers)
{
ThreadpoolMgr::AdjustMaxWorkersActive();
tal.Release();
}
- if (needReset)
- pThread->InternalReset (FALSE, TRUE, TRUE, FALSE);
-
HELPER_METHOD_FRAME_END();
}
{
WRAPPER_NO_CONTRACT;
#ifndef DACCESS_COMPILE
- LONG count = m_outstandingThreadRequestCount;
+ LONG count = VolatileLoad(&m_outstandingThreadRequestCount);
while (count < (LONG)ThreadpoolMgr::NumberOfProcessors)
{
LONG prevCount = FastInterlockCompareExchange(&m_outstandingThreadRequestCount, count+1, count);
bool FORCEINLINE UnManagedPerAppDomainTPCount::TakeActiveRequest()
{
LIMITED_METHOD_CONTRACT;
- LONG count = m_outstandingThreadRequestCount;
+ LONG count = VolatileLoad(&m_outstandingThreadRequestCount);
while (count > 0)
{
_ASSERTE(m_id.m_dwId != 0);
#ifndef DACCESS_COMPILE
- LONG count = m_numRequestsPending;
+ LONG count = VolatileLoad(&m_numRequestsPending);
while (count != ADUnloading)
{
LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, count+1, count);
if (bADU)
{
- m_numRequestsPending = ADUnloading;
+ VolatileStore(&m_numRequestsPending, ADUnloading);
}
else
{
- LONG count = m_numRequestsPending;
- while (count != ADUnloading && count > 0)
+ LONG count = VolatileLoad(&m_numRequestsPending);
+ // Test is: count > 0 && count != ADUnloading
+ // Since: const ADUnloading == -1
+ // Both are tested: (count > 0) means following also true (count != ADUnloading)
+ while (count > 0)
{
LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, 0, count);
if (prev == count)
bool ManagedPerAppDomainTPCount::TakeActiveRequest()
{
LIMITED_METHOD_CONTRACT;
- LONG count = m_numRequestsPending;
- while (count != ADUnloading && count > 0)
+ LONG count = VolatileLoad(&m_numRequestsPending);
+ // Test is: count > 0 && count != ADUnloading
+ // Since: const ADUnloading == -1
+ // Both are tested: (count > 0) means following also true (count != ADUnloading)
+ while (count > 0)
{
LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, count-1, count);
if (prev == count)
// it should be, but if it's smaller then we will be permanently out of sync with the
// AD.
//
- m_numRequestsPending = ThreadpoolMgr::NumberOfProcessors;
+ VolatileStore(&m_numRequestsPending, (LONG)ThreadpoolMgr::NumberOfProcessors);
if (!CLRThreadpoolHosted() && ThreadpoolMgr::IsInitialized())
{
ThreadpoolMgr::MaybeAddWorkingWorker();
inline void ResetState()
{
LIMITED_METHOD_CONTRACT;
- m_numRequestsPending = 0;
+ VolatileStore(&m_numRequestsPending, (LONG)0);
m_id.m_dwId = 0;
}
inline BOOL IsRequestPending()
{
LIMITED_METHOD_CONTRACT;
- return m_numRequestsPending != ADUnloading && m_numRequestsPending > 0;
+
+ LONG count = VolatileLoad(&m_numRequestsPending);
+ return count != ADUnloading && count > 0;
}
void SetAppDomainRequestsActive();
//has started running yet. That implies, no requests should be pending
//or dispatched to this structure yet.
- _ASSERTE(m_numRequestsPending != ADUnloading);
+ _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading);
_ASSERTE(m_id.m_dwId == 0);
m_id = id;
//has started running yet. That implies, no requests should be pending
//or dispatched to this structure yet.
- _ASSERTE(m_numRequestsPending != ADUnloading);
+ _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading);
_ASSERTE(m_id.m_dwId == 0);
_ASSERTE(m_index.m_dwIndex == UNUSED_THREADPOOL_INDEX);
//added removed at this time. So, make sure that the per-appdomain structures that
//have been cleared(reclaimed) don't have any pending requests to them.
- _ASSERTE(m_numRequestsPending != ADUnloading);
+ _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading);
_ASSERTE(m_id.m_dwId == 0);
return TRUE;
inline void SetAppDomainUnloading()
{
LIMITED_METHOD_CONTRACT;
- m_numRequestsPending = ADUnloading;
+ VolatileStore(&m_numRequestsPending, ADUnloading);
}
inline void ClearAppDomainUnloading();
inline BOOL IsAppDomainUnloading()
{
- return m_numRequestsPending.Load() == ADUnloading;
+ return VolatileLoad(&m_numRequestsPending) == ADUnloading;
}
void DispatchWorkItem(bool* foundWork, bool* wasNotRecalled);
private:
struct {
BYTE padding1[64]; // padding to ensure own cache line
- Volatile<LONG> m_numRequestsPending;
+ // Only use with VolatileLoad+VolatileStore+FastInterlockCompareExchange
+ LONG m_numRequestsPending;
BYTE padding2[64]; // padding to ensure own cache line
ADID m_id;
BYTE padding3[64]; // padding to ensure own cache line
{
LIMITED_METHOD_CONTRACT;
m_NumRequests = 0;
- m_outstandingThreadRequestCount = 0;
+ VolatileStore(&m_outstandingThreadRequestCount, (LONG)0);
}
inline BOOL IsRequestPending()
{
LIMITED_METHOD_CONTRACT;
- return m_outstandingThreadRequestCount != 0 ? TRUE : FALSE;
+ return VolatileLoad(&m_outstandingThreadRequestCount) != (LONG)0 ? TRUE : FALSE;
}
void SetAppDomainRequestsActive();
inline void ClearAppDomainRequestsActive(BOOL bADU)
{
LIMITED_METHOD_CONTRACT;
- m_outstandingThreadRequestCount = 0;
+ VolatileStore(&m_outstandingThreadRequestCount, (LONG)0);
}
bool TakeActiveRequest();
BYTE padding1[64]; // padding to ensure own cache line
ULONG m_NumRequests;
BYTE padding2[64]; // padding to ensure own cache line
- Volatile<LONG> m_outstandingThreadRequestCount;
+ // Only use with VolatileLoad+VolatileStore+FastInterlockCompareExchange
+ LONG m_outstandingThreadRequestCount;
BYTE padding3[64]; // padding to ensure own cache line
SpinLock m_lock;
};
HillClimbing ThreadpoolMgr::HillClimbingInstance;
-Volatile<LONG> ThreadpoolMgr::PriorCompletedWorkRequests = 0;
-Volatile<DWORD> ThreadpoolMgr::PriorCompletedWorkRequestsTime;
-Volatile<DWORD> ThreadpoolMgr::NextCompletedWorkRequestsTime;
+BYTE ThreadpoolMgr::padding1[64];
+LONG ThreadpoolMgr::PriorCompletedWorkRequests = 0;
+DWORD ThreadpoolMgr::PriorCompletedWorkRequestsTime;
+DWORD ThreadpoolMgr::NextCompletedWorkRequestsTime;
+BYTE ThreadpoolMgr::padding2[64];
+
LARGE_INTEGER ThreadpoolMgr::CurrentSampleStartTime;
int ThreadpoolMgr::ThreadAdjustmentInterval;
DWORD currentTicks = GetTickCount();
LONG totalNumCompletions = Thread::GetTotalThreadPoolCompletionCount();
- LONG numCompletions = totalNumCompletions - PriorCompletedWorkRequests;
+ LONG numCompletions = totalNumCompletions - VolatileLoad(&PriorCompletedWorkRequests);
LARGE_INTEGER startTime = CurrentSampleStartTime;
LARGE_INTEGER endTime;
}
}
- PriorCompletedWorkRequests = totalNumCompletions;
+ // Memory fences below writes
+ VolatileStore(&PriorCompletedWorkRequests, totalNumCompletions);
PriorCompletedWorkRequestsTime = currentTicks;
- NextCompletedWorkRequestsTime = PriorCompletedWorkRequestsTime + ThreadAdjustmentInterval;
+ NextCompletedWorkRequestsTime = currentTicks + ThreadAdjustmentInterval;
CurrentSampleStartTime = endTime;
}
}
if (CLRThreadpoolHosted())
return false;
- DWORD requiredInterval = NextCompletedWorkRequestsTime - PriorCompletedWorkRequestsTime;
- DWORD elapsedInterval = GetTickCount() - PriorCompletedWorkRequestsTime;
+ DWORD priorTime = PriorCompletedWorkRequestsTime;
+ DWORD requiredInterval = VolatileLoad(&NextCompletedWorkRequestsTime) - priorTime; // fences above read
+ DWORD elapsedInterval = GetTickCount() - priorTime;
if (elapsedInterval >= requiredInterval)
{
ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts();
static HillClimbing HillClimbingInstance;
- static Volatile<LONG> PriorCompletedWorkRequests;
- static Volatile<DWORD> PriorCompletedWorkRequestsTime;
- static Volatile<DWORD> NextCompletedWorkRequestsTime;
+ static BYTE padding1[64]; // padding to ensure own cache line
+
+ static LONG PriorCompletedWorkRequests;
+ static DWORD PriorCompletedWorkRequestsTime;
+ static DWORD NextCompletedWorkRequestsTime;
+
+ static BYTE padding2[64]; // padding to ensure own cache line
static LARGE_INTEGER CurrentSampleStartTime;