internal ClrThreadPool()

in src/Microsoft.Diagnostics.Runtime/ClrThreadPool.cs [82:155]


        internal ClrThreadPool(ClrRuntime runtime, IAbstractLegacyThreadPool? helpers)
        {
            _runtime = runtime;
            _legacyData = helpers;


            LegacyThreadPoolInfo tpData = default;
            HasLegacyData = _legacyData is not null && _legacyData.GetLegacyThreadPoolData(out tpData);

            ClrAppDomain domain = GetDomain();

            GetPortableOrWindowsThreadPoolInfo(domain,
                                            out bool usingPortableThreadPool,
                                            out ClrObject portableThreadPool,
                                            out bool usingWindowsThreadPool,
                                            out ClrType? windowsThreadPoolType);

            UsingPortableThreadPool = usingPortableThreadPool;
            UsingWindowsThreadPool = usingWindowsThreadPool;

            Initialized = UsingPortableThreadPool || UsingWindowsThreadPool || HasLegacyData;

            if (UsingWindowsThreadPool)
            {
                ClrStaticField threadCountField = windowsThreadPoolType!.GetStaticFieldByName("s_threadCount")!;
                WindowsThreadPoolThreadCount = threadCountField.Read<int>(domain);
                return;
            }

            if (UsingPortableThreadPool)
            {
                CpuUtilization = portableThreadPool.ReadField<int>("_cpuUtilization");
                MinThreads = portableThreadPool.ReadField<ushort>("_minThreads");
                MaxThreads = portableThreadPool.ReadField<ushort>("_maxThreads");

                ClrValueType counts = portableThreadPool.ReadValueTypeField("_separated").ReadValueTypeField("counts").ReadValueTypeField("_data");
                ulong dataValue = counts.ReadField<ulong>("m_value");

                int processingWorkCount = (ushort)(dataValue & 0xffff);
                int existingThreadCount = (ushort)((dataValue >> 16) & 0xffff);

                IdleWorkerThreads = existingThreadCount - processingWorkCount;
                ActiveWorkerThreads = processingWorkCount;

                RetiredWorkerThreads = 0;
            }
            else if (HasLegacyData)
            {
                CpuUtilization = tpData.CpuUtilization;
                MinThreads = tpData.MinLimitTotalWorkerThreads;
                MaxThreads = tpData.MaxLimitTotalWorkerThreads;
                IdleWorkerThreads = tpData.NumIdleWorkerThreads;
                ActiveWorkerThreads = tpData.NumWorkingWorkerThreads;
                RetiredWorkerThreads = tpData.NumRetiredWorkerThreads;

                _nativeLogAddress = tpData.HillClimbingLog;
                _nativeLogStart = tpData.HillClimbingLogFirstIndex;
                _nativeLogSize = tpData.HillClimbingLogSize;

                _firstLegacyWorkRequest = tpData.FirstUnmanagedWorkRequest;
                _asyncTimerFunction = tpData.AsyncTimerCallbackCompletionFPtr;
            }

            // The legacy IO completion thread pool may also be used while the portable thread pool is being used for worker threads
            if (HasLegacyData)
            {
                TotalCompletionPorts = tpData.NumCPThreads;
                FreeCompletionPorts = tpData.NumFreeCPThreads;
                MaxFreeCompletionPorts = tpData.MaxFreeCPThreads;
                CompletionPortCurrentLimit = tpData.CurrentLimitTotalCPThreads;
                MaxCompletionPorts = tpData.MaxLimitTotalCPThreads;
                MinCompletionPorts = tpData.MinLimitTotalCPThreads;
            }
        }