/// <summary> /// Adjust scheduling options. /// </summary> /// <param name="settings">The new scheduling options. </param> public void SetSchedulingOptions(MultiThreadSchedulingSettings settings) { if (_disposalComplete != null) { throw new ObjectDisposedException("Cannot set the number of threads for a disposed scheduler. "); } int numThreads; if ((settings.Mode & MultiThreadCreationMode.OneThreadPerLogicalCpu) != 0) { // FIXME filter this list based on process CPU affinity var cpuInfo = CpuTopologyInfo.GetList(); if ((settings.Mode & MultiThreadCreationMode.OneThreadPerCpuCore) == MultiThreadCreationMode.OneThreadPerCpuCore) { numThreads = CpuTopologyInfo.CountNumberOfCores(cpuInfo); } else { numThreads = cpuInfo.Length; } settings.NumberOfThreads = numThreads; } else { numThreads = settings.NumberOfThreads; if (numThreads <= 0) { throw new ArgumentOutOfRangeException($"{nameof(MultiThreadSchedulingSettings)}.{nameof(MultiThreadSchedulingSettings.NumberOfThreads)} is out of range: {numThreads}"); } } // Cap at CPU quota, if requested. // FIXME For dynamic updates to CPU quota we should read the quota ourselves if ((settings.Mode & MultiThreadCreationMode.CapThreadsAtCpuQuota) != 0) { numThreads = Math.Min(numThreads, Environment.ProcessorCount); } if (numThreads == 0) { numThreads = 1; } SetNumberOfThreads(numThreads, settings.ThreadPriority); // Publish new options, if SetNumberOfThreads does not fail SchedulingOptions = settings; }
private static CpuTopologyInfo[] Linux_GetList() { var cpuMask = new BitMask(stackalloc ulong[512]); int cpuCount = 0; foreach (var fullDirName in Directory.EnumerateDirectories("/sys/devices/system/cpu/")) { if (Linux_IsSysFsCpuDirectory(fullDirName, out var cpuIdShort)) { cpuMask[cpuIdShort] = true; cpuCount++; } } var infoArray = new CpuTopologyInfo[cpuCount]; int cpuId = -1; for (int i = 0; (cpuId = cpuMask.GetIndexOfNextOnBit(++cpuId)) >= 0; ++i) { infoArray[i] = Linux_ReadFromSysFsFile(cpuId); } return(infoArray); }