From: Koundinya Veluri Date: Tue, 11 Apr 2017 02:48:54 +0000 (-0700) Subject: Fix some static methods on ThreadPool to wait for initialization (#10869) X-Git-Tag: accepted/tizen/base/20180629.140029~1476 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cdde90945fe82715a4f58f090925a0ca78db11e6;p=platform%2Fupstream%2Fcoreclr.git Fix some static methods on ThreadPool to wait for initialization (#10869) Fix for part of #10521 --- diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index da6c1b2..bc84762 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -553,7 +553,7 @@ BOOL ThreadpoolMgr::SetMaxThreadsHelper(DWORD MaxWorkerThreads, /************************************************************************/ BOOL ThreadpoolMgr::SetMaxThreads(DWORD MaxWorkerThreads, - DWORD MaxIOCompletionThreads) + DWORD MaxIOCompletionThreads) { CONTRACTL { @@ -563,31 +563,13 @@ BOOL ThreadpoolMgr::SetMaxThreads(DWORD MaxWorkerThreads, } CONTRACTL_END; + EnsureInitialized(); - if (IsInitialized()) - { - return SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads); - } - - if (InterlockedCompareExchange(&Initialization, 1, 0) == 0) - { - Initialize(); - - BOOL helper_result = FALSE; - helper_result = SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads); - - Initialization = -1; - return helper_result; - } - else // someone else is initializing. Too late, return false - { - return FALSE; - } - + return SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads); } BOOL ThreadpoolMgr::GetMaxThreads(DWORD* MaxWorkerThreads, - DWORD* MaxIOCompletionThreads) + DWORD* MaxIOCompletionThreads) { LIMITED_METHOD_CONTRACT; @@ -598,44 +580,15 @@ BOOL ThreadpoolMgr::GetMaxThreads(DWORD* MaxWorkerThreads, return FALSE; } - if (IsInitialized()) - { - *MaxWorkerThreads = (DWORD)MaxLimitTotalWorkerThreads; - *MaxIOCompletionThreads = MaxLimitTotalCPThreads; - } - else - { - BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), *MaxWorkerThreads = 1024); - - //ThreadPool_CPUGroup - CPUGroupInfo::EnsureInitialized(); - if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) - NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors(); - else - NumberOfProcessors = GetCurrentProcessCpuCount(); - DWORD min = GetForceMinWorkerThreadsValue(); - if (min == 0) - min = NumberOfProcessors; - - DWORD forceMax = GetForceMaxWorkerThreadsValue(); - if (forceMax > 0) - { - *MaxWorkerThreads = forceMax; - } - else - { - *MaxWorkerThreads = GetDefaultMaxLimitWorkerThreads(min); - } - - END_SO_INTOLERANT_CODE; + EnsureInitialized(); - *MaxIOCompletionThreads = MaxLimitTotalCPThreads; - } + *MaxWorkerThreads = (DWORD)MaxLimitTotalWorkerThreads; + *MaxIOCompletionThreads = MaxLimitTotalCPThreads; return TRUE; } BOOL ThreadpoolMgr::SetMinThreads(DWORD MinWorkerThreads, - DWORD MinIOCompletionThreads) + DWORD MinIOCompletionThreads) { CONTRACTL { @@ -645,75 +598,61 @@ BOOL ThreadpoolMgr::SetMinThreads(DWORD MinWorkerThreads, } CONTRACTL_END; + EnsureInitialized(); - if (!IsInitialized()) - { - if (InterlockedCompareExchange(&Initialization, 1, 0) == 0) - { - Initialize(); - Initialization = -1; - } - } + // doesn't need to be WorkerCS, but using it to avoid race condition between setting min and max, and didn't want to create a new CS. + CrstHolder csh(&WorkerCriticalSection); - if (IsInitialized()) - { - // doesn't need to be WorkerCS, but using it to avoid race condition between setting min and max, and didn't want to create a new CS. - CrstHolder csh(&WorkerCriticalSection); + BOOL init_result = FALSE; - BOOL init_result = false; + if (MinWorkerThreads >= 0 && MinIOCompletionThreads >= 0 && + MinWorkerThreads <= (DWORD) MaxLimitTotalWorkerThreads && + MinIOCompletionThreads <= (DWORD) MaxLimitTotalCPThreads) + { + BEGIN_SO_INTOLERANT_CODE(GetThread()); - if (MinWorkerThreads >= 0 && MinIOCompletionThreads >= 0 && - MinWorkerThreads <= (DWORD) MaxLimitTotalWorkerThreads && - MinIOCompletionThreads <= (DWORD) MaxLimitTotalCPThreads) + if (GetForceMinWorkerThreadsValue() == 0) { - BEGIN_SO_INTOLERANT_CODE(GetThread()); + MinLimitTotalWorkerThreads = min(MinWorkerThreads, (DWORD)ThreadCounter::MaxPossibleCount); - if (GetForceMinWorkerThreadsValue() == 0) + ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts(); + while (counts.MaxWorking < MinLimitTotalWorkerThreads) { - MinLimitTotalWorkerThreads = min(MinWorkerThreads, (DWORD)ThreadCounter::MaxPossibleCount); + ThreadCounter::Counts newCounts = counts; + newCounts.MaxWorking = MinLimitTotalWorkerThreads; - ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts(); - while (counts.MaxWorking < MinLimitTotalWorkerThreads) + ThreadCounter::Counts oldCounts = WorkerCounter.CompareExchangeCounts(newCounts, counts); + if (oldCounts == counts) { - ThreadCounter::Counts newCounts = counts; - newCounts.MaxWorking = MinLimitTotalWorkerThreads; - - ThreadCounter::Counts oldCounts = WorkerCounter.CompareExchangeCounts(newCounts, counts); - if (oldCounts == counts) - { - counts = newCounts; + counts = newCounts; - // if we increased the limit, and there are pending workitems, we need - // to dispatch a thread to process the work. - if (newCounts.MaxWorking > oldCounts.MaxWorking && - PerAppDomainTPCountList::AreRequestsPendingInAnyAppDomains()) - { - MaybeAddWorkingWorker(); - } - } - else + // if we increased the limit, and there are pending workitems, we need + // to dispatch a thread to process the work. + if (newCounts.MaxWorking > oldCounts.MaxWorking && + PerAppDomainTPCountList::AreRequestsPendingInAnyAppDomains()) { - counts = oldCounts; + MaybeAddWorkingWorker(); } } + else + { + counts = oldCounts; + } } + } - END_SO_INTOLERANT_CODE; - - MinLimitTotalCPThreads = min(MinIOCompletionThreads, (DWORD)ThreadCounter::MaxPossibleCount); + END_SO_INTOLERANT_CODE; - init_result = TRUE; - } + MinLimitTotalCPThreads = min(MinIOCompletionThreads, (DWORD)ThreadCounter::MaxPossibleCount); - return init_result; + init_result = TRUE; } - // someone else is initializing. Too late, return false - return FALSE; + return init_result; } BOOL ThreadpoolMgr::GetMinThreads(DWORD* MinWorkerThreads, - DWORD* MinIOCompletionThreads) + DWORD* MinIOCompletionThreads) { LIMITED_METHOD_CONTRACT; @@ -724,25 +663,10 @@ BOOL ThreadpoolMgr::GetMinThreads(DWORD* MinWorkerThreads, return FALSE; } - if (IsInitialized()) - { - *MinWorkerThreads = (DWORD)MinLimitTotalWorkerThreads; - *MinIOCompletionThreads = MinLimitTotalCPThreads; - } - else - { - CPUGroupInfo::EnsureInitialized(); - if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) - NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors(); - else - NumberOfProcessors = GetCurrentProcessCpuCount(); - DWORD forceMin; - BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), forceMin=0); - forceMin = GetForceMinWorkerThreadsValue(); - END_SO_INTOLERANT_CODE; - *MinWorkerThreads = forceMin > 0 ? forceMin : NumberOfProcessors; - *MinIOCompletionThreads = NumberOfProcessors; - } + EnsureInitialized(); + + *MinWorkerThreads = (DWORD)MinLimitTotalWorkerThreads; + *MinIOCompletionThreads = MinLimitTotalCPThreads; return TRUE; } @@ -751,32 +675,26 @@ BOOL ThreadpoolMgr::GetAvailableThreads(DWORD* AvailableWorkerThreads, { LIMITED_METHOD_CONTRACT; - if (IsInitialized()) + if (!AvailableWorkerThreads || !AvailableIOCompletionThreads) { + SetLastHRError(ERROR_INVALID_DATA); + return FALSE; + } - if (!AvailableWorkerThreads || !AvailableIOCompletionThreads) - { - SetLastHRError(ERROR_INVALID_DATA); - return FALSE; - } + EnsureInitialized(); - ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts(); + ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts(); - if (MaxLimitTotalWorkerThreads < counts.NumActive) - *AvailableWorkerThreads = 0; - else - *AvailableWorkerThreads = MaxLimitTotalWorkerThreads - counts.NumWorking; + if (MaxLimitTotalWorkerThreads < counts.NumActive) + *AvailableWorkerThreads = 0; + else + *AvailableWorkerThreads = MaxLimitTotalWorkerThreads - counts.NumWorking; - counts = CPThreadCounter.GetCleanCounts(); - if (MaxLimitTotalCPThreads < counts.NumActive) - *AvailableIOCompletionThreads = counts.NumActive - counts.NumWorking; - else - *AvailableIOCompletionThreads = MaxLimitTotalCPThreads - counts.NumWorking; - } + counts = CPThreadCounter.GetCleanCounts(); + if (MaxLimitTotalCPThreads < counts.NumActive) + *AvailableIOCompletionThreads = counts.NumActive - counts.NumWorking; else - { - GetMaxThreads(AvailableWorkerThreads,AvailableIOCompletionThreads); - } + *AvailableIOCompletionThreads = MaxLimitTotalCPThreads - counts.NumWorking; return TRUE; }