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

Commit cdde909

Browse files
author
Koundinya Veluri
authored
Fix some static methods on ThreadPool to wait for initialization (#10869)
Fix for part of #10521
1 parent 7e5e9c0 commit cdde909

File tree

1 file changed

+59
-141
lines changed

1 file changed

+59
-141
lines changed

src/vm/win32threadpool.cpp

Lines changed: 59 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ BOOL ThreadpoolMgr::SetMaxThreadsHelper(DWORD MaxWorkerThreads,
553553

554554
/************************************************************************/
555555
BOOL ThreadpoolMgr::SetMaxThreads(DWORD MaxWorkerThreads,
556-
DWORD MaxIOCompletionThreads)
556+
DWORD MaxIOCompletionThreads)
557557
{
558558
CONTRACTL
559559
{
@@ -563,31 +563,13 @@ BOOL ThreadpoolMgr::SetMaxThreads(DWORD MaxWorkerThreads,
563563
}
564564
CONTRACTL_END;
565565

566+
EnsureInitialized();
566567

567-
if (IsInitialized())
568-
{
569-
return SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads);
570-
}
571-
572-
if (InterlockedCompareExchange(&Initialization, 1, 0) == 0)
573-
{
574-
Initialize();
575-
576-
BOOL helper_result = FALSE;
577-
helper_result = SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads);
578-
579-
Initialization = -1;
580-
return helper_result;
581-
}
582-
else // someone else is initializing. Too late, return false
583-
{
584-
return FALSE;
585-
}
586-
568+
return SetMaxThreadsHelper(MaxWorkerThreads, MaxIOCompletionThreads);
587569
}
588570

589571
BOOL ThreadpoolMgr::GetMaxThreads(DWORD* MaxWorkerThreads,
590-
DWORD* MaxIOCompletionThreads)
572+
DWORD* MaxIOCompletionThreads)
591573
{
592574
LIMITED_METHOD_CONTRACT;
593575

@@ -598,44 +580,15 @@ BOOL ThreadpoolMgr::GetMaxThreads(DWORD* MaxWorkerThreads,
598580
return FALSE;
599581
}
600582

601-
if (IsInitialized())
602-
{
603-
*MaxWorkerThreads = (DWORD)MaxLimitTotalWorkerThreads;
604-
*MaxIOCompletionThreads = MaxLimitTotalCPThreads;
605-
}
606-
else
607-
{
608-
BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), *MaxWorkerThreads = 1024);
609-
610-
//ThreadPool_CPUGroup
611-
CPUGroupInfo::EnsureInitialized();
612-
if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups())
613-
NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors();
614-
else
615-
NumberOfProcessors = GetCurrentProcessCpuCount();
616-
DWORD min = GetForceMinWorkerThreadsValue();
617-
if (min == 0)
618-
min = NumberOfProcessors;
619-
620-
DWORD forceMax = GetForceMaxWorkerThreadsValue();
621-
if (forceMax > 0)
622-
{
623-
*MaxWorkerThreads = forceMax;
624-
}
625-
else
626-
{
627-
*MaxWorkerThreads = GetDefaultMaxLimitWorkerThreads(min);
628-
}
629-
630-
END_SO_INTOLERANT_CODE;
583+
EnsureInitialized();
631584

632-
*MaxIOCompletionThreads = MaxLimitTotalCPThreads;
633-
}
585+
*MaxWorkerThreads = (DWORD)MaxLimitTotalWorkerThreads;
586+
*MaxIOCompletionThreads = MaxLimitTotalCPThreads;
634587
return TRUE;
635588
}
636589

637590
BOOL ThreadpoolMgr::SetMinThreads(DWORD MinWorkerThreads,
638-
DWORD MinIOCompletionThreads)
591+
DWORD MinIOCompletionThreads)
639592
{
640593
CONTRACTL
641594
{
@@ -645,75 +598,61 @@ BOOL ThreadpoolMgr::SetMinThreads(DWORD MinWorkerThreads,
645598
}
646599
CONTRACTL_END;
647600

601+
EnsureInitialized();
648602

649-
if (!IsInitialized())
650-
{
651-
if (InterlockedCompareExchange(&Initialization, 1, 0) == 0)
652-
{
653-
Initialize();
654-
Initialization = -1;
655-
}
656-
}
603+
// 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.
604+
CrstHolder csh(&WorkerCriticalSection);
657605

658-
if (IsInitialized())
659-
{
660-
// 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.
661-
CrstHolder csh(&WorkerCriticalSection);
606+
BOOL init_result = FALSE;
662607

663-
BOOL init_result = false;
608+
if (MinWorkerThreads >= 0 && MinIOCompletionThreads >= 0 &&
609+
MinWorkerThreads <= (DWORD) MaxLimitTotalWorkerThreads &&
610+
MinIOCompletionThreads <= (DWORD) MaxLimitTotalCPThreads)
611+
{
612+
BEGIN_SO_INTOLERANT_CODE(GetThread());
664613

665-
if (MinWorkerThreads >= 0 && MinIOCompletionThreads >= 0 &&
666-
MinWorkerThreads <= (DWORD) MaxLimitTotalWorkerThreads &&
667-
MinIOCompletionThreads <= (DWORD) MaxLimitTotalCPThreads)
614+
if (GetForceMinWorkerThreadsValue() == 0)
668615
{
669-
BEGIN_SO_INTOLERANT_CODE(GetThread());
616+
MinLimitTotalWorkerThreads = min(MinWorkerThreads, (DWORD)ThreadCounter::MaxPossibleCount);
670617

671-
if (GetForceMinWorkerThreadsValue() == 0)
618+
ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts();
619+
while (counts.MaxWorking < MinLimitTotalWorkerThreads)
672620
{
673-
MinLimitTotalWorkerThreads = min(MinWorkerThreads, (DWORD)ThreadCounter::MaxPossibleCount);
621+
ThreadCounter::Counts newCounts = counts;
622+
newCounts.MaxWorking = MinLimitTotalWorkerThreads;
674623

675-
ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts();
676-
while (counts.MaxWorking < MinLimitTotalWorkerThreads)
624+
ThreadCounter::Counts oldCounts = WorkerCounter.CompareExchangeCounts(newCounts, counts);
625+
if (oldCounts == counts)
677626
{
678-
ThreadCounter::Counts newCounts = counts;
679-
newCounts.MaxWorking = MinLimitTotalWorkerThreads;
680-
681-
ThreadCounter::Counts oldCounts = WorkerCounter.CompareExchangeCounts(newCounts, counts);
682-
if (oldCounts == counts)
683-
{
684-
counts = newCounts;
627+
counts = newCounts;
685628

686-
// if we increased the limit, and there are pending workitems, we need
687-
// to dispatch a thread to process the work.
688-
if (newCounts.MaxWorking > oldCounts.MaxWorking &&
689-
PerAppDomainTPCountList::AreRequestsPendingInAnyAppDomains())
690-
{
691-
MaybeAddWorkingWorker();
692-
}
693-
}
694-
else
629+
// if we increased the limit, and there are pending workitems, we need
630+
// to dispatch a thread to process the work.
631+
if (newCounts.MaxWorking > oldCounts.MaxWorking &&
632+
PerAppDomainTPCountList::AreRequestsPendingInAnyAppDomains())
695633
{
696-
counts = oldCounts;
634+
MaybeAddWorkingWorker();
697635
}
698636
}
637+
else
638+
{
639+
counts = oldCounts;
640+
}
699641
}
642+
}
700643

701-
END_SO_INTOLERANT_CODE;
702-
703-
MinLimitTotalCPThreads = min(MinIOCompletionThreads, (DWORD)ThreadCounter::MaxPossibleCount);
644+
END_SO_INTOLERANT_CODE;
704645

705-
init_result = TRUE;
706-
}
646+
MinLimitTotalCPThreads = min(MinIOCompletionThreads, (DWORD)ThreadCounter::MaxPossibleCount);
707647

708-
return init_result;
648+
init_result = TRUE;
709649
}
710-
// someone else is initializing. Too late, return false
711-
return FALSE;
712650

651+
return init_result;
713652
}
714653

715654
BOOL ThreadpoolMgr::GetMinThreads(DWORD* MinWorkerThreads,
716-
DWORD* MinIOCompletionThreads)
655+
DWORD* MinIOCompletionThreads)
717656
{
718657
LIMITED_METHOD_CONTRACT;
719658

@@ -724,25 +663,10 @@ BOOL ThreadpoolMgr::GetMinThreads(DWORD* MinWorkerThreads,
724663
return FALSE;
725664
}
726665

727-
if (IsInitialized())
728-
{
729-
*MinWorkerThreads = (DWORD)MinLimitTotalWorkerThreads;
730-
*MinIOCompletionThreads = MinLimitTotalCPThreads;
731-
}
732-
else
733-
{
734-
CPUGroupInfo::EnsureInitialized();
735-
if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups())
736-
NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors();
737-
else
738-
NumberOfProcessors = GetCurrentProcessCpuCount();
739-
DWORD forceMin;
740-
BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), forceMin=0);
741-
forceMin = GetForceMinWorkerThreadsValue();
742-
END_SO_INTOLERANT_CODE;
743-
*MinWorkerThreads = forceMin > 0 ? forceMin : NumberOfProcessors;
744-
*MinIOCompletionThreads = NumberOfProcessors;
745-
}
666+
EnsureInitialized();
667+
668+
*MinWorkerThreads = (DWORD)MinLimitTotalWorkerThreads;
669+
*MinIOCompletionThreads = MinLimitTotalCPThreads;
746670
return TRUE;
747671
}
748672

@@ -751,32 +675,26 @@ BOOL ThreadpoolMgr::GetAvailableThreads(DWORD* AvailableWorkerThreads,
751675
{
752676
LIMITED_METHOD_CONTRACT;
753677

754-
if (IsInitialized())
678+
if (!AvailableWorkerThreads || !AvailableIOCompletionThreads)
755679
{
680+
SetLastHRError(ERROR_INVALID_DATA);
681+
return FALSE;
682+
}
756683

757-
if (!AvailableWorkerThreads || !AvailableIOCompletionThreads)
758-
{
759-
SetLastHRError(ERROR_INVALID_DATA);
760-
return FALSE;
761-
}
684+
EnsureInitialized();
762685

763-
ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts();
686+
ThreadCounter::Counts counts = WorkerCounter.GetCleanCounts();
764687

765-
if (MaxLimitTotalWorkerThreads < counts.NumActive)
766-
*AvailableWorkerThreads = 0;
767-
else
768-
*AvailableWorkerThreads = MaxLimitTotalWorkerThreads - counts.NumWorking;
688+
if (MaxLimitTotalWorkerThreads < counts.NumActive)
689+
*AvailableWorkerThreads = 0;
690+
else
691+
*AvailableWorkerThreads = MaxLimitTotalWorkerThreads - counts.NumWorking;
769692

770-
counts = CPThreadCounter.GetCleanCounts();
771-
if (MaxLimitTotalCPThreads < counts.NumActive)
772-
*AvailableIOCompletionThreads = counts.NumActive - counts.NumWorking;
773-
else
774-
*AvailableIOCompletionThreads = MaxLimitTotalCPThreads - counts.NumWorking;
775-
}
693+
counts = CPThreadCounter.GetCleanCounts();
694+
if (MaxLimitTotalCPThreads < counts.NumActive)
695+
*AvailableIOCompletionThreads = counts.NumActive - counts.NumWorking;
776696
else
777-
{
778-
GetMaxThreads(AvailableWorkerThreads,AvailableIOCompletionThreads);
779-
}
697+
*AvailableIOCompletionThreads = MaxLimitTotalCPThreads - counts.NumWorking;
780698
return TRUE;
781699
}
782700

0 commit comments

Comments
 (0)