示例#1
0
        private static void AppendMSRData(StringBuilder r, uint msr, GroupAffinity affinity)
        {
            uint eax, edx;

            if (Ring0.RdmsrTx(msr, out eax, out edx, affinity))
            {
                r.Append(" ");
                r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
                r.Append("  ");
                r.Append((edx).ToString("X8", CultureInfo.InvariantCulture));
                r.Append("  ");
                r.Append((eax).ToString("X8", CultureInfo.InvariantCulture));
                r.AppendLine();
            }
        }
        private static CPUID[][] GetProcessorThreads()
        {
            List <CPUID> threads = new List <CPUID>();

            for (int i = 0; i < ThreadAffinity.ProcessorGroupCount; i++)
            {
                for (int j = 0; j < 64; j++)
                {
                    try {
                        if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j)))
                        {
                            continue;
                        }
                        var cpuid = CPUID.Get(i, j);
                        if (cpuid != null)
                        {
                            threads.Add(cpuid);
                        }
                    } catch (ArgumentOutOfRangeException) {
                    }
                }
            }

            SortedDictionary <uint, List <CPUID> > processors =
                new SortedDictionary <uint, List <CPUID> >();

            foreach (CPUID thread in threads)
            {
                List <CPUID> list;
                processors.TryGetValue(thread.ProcessorId, out list);
                if (list == null)
                {
                    list = new List <CPUID>();
                    processors.Add(thread.ProcessorId, list);
                }
                list.Add(thread);
            }

            CPUID[][] processorThreads = new CPUID[processors.Count][];
            int       index            = 0;

            foreach (List <CPUID> list in processors.Values)
            {
                processorThreads[index] = list.ToArray();
                index++;
            }
            return(processorThreads);
        }
示例#3
0
        public override void Update()
        {
            if (HasTimeStampCounter && _isInvariantTimeStampCounter)
            {
                // make sure always the same thread is used
                GroupAffinity previousAffinity = ThreadAffinity.Set(_cpuId[0][0].Affinity);

                // read time before and after getting the TSC to estimate the error
                long  firstTime      = Stopwatch.GetTimestamp();
                ulong timeStampCount = OpCode.Rdtsc();
                long  time           = Stopwatch.GetTimestamp();

                // restore the thread affinity mask
                ThreadAffinity.Set(previousAffinity);

                double delta = (double)(time - _lastTime) / Stopwatch.Frequency;
                double error = (double)(time - firstTime) / Stopwatch.Frequency;

                // only use data if they are measured accurate enough (max 0.1ms delay)
                if (error < 0.0001)
                {
                    // ignore the first reading because there are no initial values
                    // ignore readings with too large or too small time window
                    if (_lastTime != 0 && delta > 0.5 && delta < 2)
                    {
                        // update the TSC frequency with the new value
                        TimeStampCounterFrequency = (timeStampCount - _lastTimeStampCount) / (1e6 * delta);
                    }

                    _lastTimeStampCount = timeStampCount;
                    _lastTime           = time;
                }
            }

            if (_cpuLoad.IsAvailable)
            {
                _cpuLoad.Update();
                for (int i = 0; i < _coreLoads.Length; i++)
                {
                    _coreLoads[i].Value = _cpuLoad.GetCoreLoad(i);
                }

                if (_totalLoad != null)
                {
                    _totalLoad.Value = _cpuLoad.GetTotalLoad();
                }
            }
        }
示例#4
0
        public static void MessWithAffinity(int taskNum)
        {
            Thread        thread       = Thread.CurrentThread;
            int           groupCount   = GetActiveProcessorGroupCount();
            IntPtr        threadHandle = GetCurrentThread();
            short         theNewGroup  = (short)(taskNum % groupCount);
            GroupAffinity ga           = new GroupAffinity();
            GroupAffinity ga1          = new GroupAffinity();
            bool          retVal       = GetThreadGroupAffinity(threadHandle, ref ga);
            int           error        = Marshal.GetLastWin32Error();

            if (retVal == true)
            {
                ga.group = theNewGroup;
                retVal   = SetThreadGroupAffinity(threadHandle, ref ga, ref ga1);
                if (retVal != true)
                {
                    error = Marshal.GetLastWin32Error();
                }
            }
        }
示例#5
0
        public static CPUID Get(int group, int thread)
        {
            if (thread >= 64)
            {
                return(null);
            }

            var affinity = GroupAffinity.Single((ushort)group, thread);

            var previousAffinity = ThreadAffinity.Set(affinity);

            if (previousAffinity == GroupAffinity.Undefined)
            {
                return(null);
            }

            try {
                return(new CPUID(group, thread, affinity));
            } finally {
                ThreadAffinity.Set(previousAffinity);
            }
        }
示例#6
0
            public Core(int index, CPUID[] threads, AMD17CPU cpu, ISettings settings)
            {
                this.cpu      = cpu;
                this.affinity = threads[0].Affinity;

                string coreString = cpu.CoreString(index);

                this.powerSensor =
                    new Sensor(coreString, index + 2, SensorType.Power, cpu, settings);
                this.clockSensor =
                    new Sensor(coreString, index + 1, SensorType.Clock, cpu, settings);

                if (cpu.energyUnitMultiplier != 0)
                {
                    if (Ring0.RdmsrTx(MSR_CORE_ENERGY_STAT, out uint energyConsumed,
                                      out _, affinity))
                    {
                        lastEnergyTime     = DateTime.UtcNow;
                        lastEnergyConsumed = energyConsumed;
                        cpu.ActivateSensor(powerSensor);
                    }
                }
            }
示例#7
0
            public void UpdateSensors()
            {
                NumaNode node  = Nodes[0];
                Core     core  = node?.Cores[0];
                CpuId    cpuId = core?.Threads[0];

                if (cpuId == null)
                {
                    return;
                }


                GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId.Affinity);

                // MSRC001_0299
                // TU [19:16]
                // ESU [12:8] -> Unit 15.3 micro Joule per increment
                // PU [3:0]
                Ring0.ReadMsr(MSR_PWR_UNIT, out uint _, out uint _);

                // MSRC001_029B
                // total_energy [31:0]
                DateTime sampleTime = DateTime.Now;

                Ring0.ReadMsr(MSR_PKG_ENERGY_STAT, out uint eax, out _);

                uint totalEnergy = eax;

                uint smuSvi0Tfn       = 0;
                uint smuSvi0TelPlane0 = 0;
                uint smuSvi0TelPlane1 = 0;

                if (Ring0.WaitPciBusMutex(10))
                {
                    // THM_TCON_CUR_TMP
                    // CUR_TEMP [31:21]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature);

                    // SVI0_TFN_PLANE0 [0]
                    // SVI0_TFN_PLANE1 [1]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0Tfn);

                    bool supportsPerCcdTemperatures = false;

                    // TODO: find a better way because these will probably keep changing in the future.

                    uint sviPlane0Offset;
                    uint sviPlane1Offset;
                    switch (cpuId.Model)
                    {
                    case 0x31:     // Threadripper 3000.
                    {
                        sviPlane0Offset            = F17H_M01H_SVI + 0x14;
                        sviPlane1Offset            = F17H_M01H_SVI + 0x10;
                        supportsPerCcdTemperatures = true;
                        break;
                    }

                    case 0x71:     // Zen 2.
                    case 0x21:     // Zen 3.
                    {
                        sviPlane0Offset            = F17H_M01H_SVI + 0x10;
                        sviPlane1Offset            = F17H_M01H_SVI + 0xC;
                        supportsPerCcdTemperatures = true;
                        break;
                    }

                    default:     // Zen and Zen+.
                    {
                        sviPlane0Offset = F17H_M01H_SVI + 0xC;
                        sviPlane1Offset = F17H_M01H_SVI + 0x10;
                        break;
                    }
                    }

                    // SVI0_PLANE0_VDDCOR [24:16]
                    // SVI0_PLANE0_IDDCOR [7:0]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane0);

                    // SVI0_PLANE1_VDDCOR [24:16]
                    // SVI0_PLANE1_IDDCOR [7:0]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane1);

                    ThreadAffinity.Set(previousAffinity);

                    // power consumption
                    // power.Value = (float) ((double)pu * 0.125);
                    // esu = 15.3 micro Joule per increment
                    if (_lastPwrTime.Ticks == 0)
                    {
                        _lastPwrTime  = sampleTime;
                        _lastPwrValue = totalEnergy;
                    }

                    // ticks diff
                    TimeSpan time = sampleTime - _lastPwrTime;
                    long     pwr;
                    if (_lastPwrValue <= totalEnergy)
                    {
                        pwr = totalEnergy - _lastPwrValue;
                    }
                    else
                    {
                        pwr = (0xffffffff - _lastPwrValue) + totalEnergy;
                    }

                    // update for next sample
                    _lastPwrTime  = sampleTime;
                    _lastPwrValue = totalEnergy;

                    double energy = 15.3e-6 * pwr;
                    energy /= time.TotalSeconds;

                    if (!double.IsNaN(energy))
                    {
                        _packagePower.Value = (float)energy;
                    }

                    // current temp Bit [31:21]
                    // If bit 19 of the Temperature Control register is set, there is an additional offset of 49 degrees C.
                    bool tempOffsetFlag = (temperature & F17H_TEMP_OFFSET_FLAG) != 0;
                    temperature = (temperature >> 21) * 125;

                    float offset = 0.0f;

                    // Offset table: https://github.com/torvalds/linux/blob/master/drivers/hwmon/k10temp.c#L78
                    if (string.IsNullOrWhiteSpace(cpuId.Name))
                    {
                        offset = 0;
                    }
                    else if (cpuId.Name.Contains("1600X") || cpuId.Name.Contains("1700X") || cpuId.Name.Contains("1800X"))
                    {
                        offset = -20.0f;
                    }
                    else if (cpuId.Name.Contains("Threadripper 19") || cpuId.Name.Contains("Threadripper 29"))
                    {
                        offset = -27.0f;
                    }
                    else if (cpuId.Name.Contains("2700X"))
                    {
                        offset = -10.0f;
                    }

                    float t = temperature * 0.001f;
                    if (tempOffsetFlag)
                    {
                        t += -49.0f;
                    }

                    if (offset < 0)
                    {
                        _coreTemperatureTctl.Value = t;
                        _coreTemperatureTdie.Value = t + offset;

                        _cpu.ActivateSensor(_coreTemperatureTctl);
                        _cpu.ActivateSensor(_coreTemperatureTdie);
                    }
                    else
                    {
                        // Zen 2 doesn't have an offset so Tdie and Tctl are the same.
                        _coreTemperatureTctlTdie.Value = t;
                        _cpu.ActivateSensor(_coreTemperatureTctlTdie);
                    }

                    // Tested only on R5 3600 & Threadripper 3960X.
                    if (supportsPerCcdTemperatures)
                    {
                        for (uint i = 0; i < _ccdTemperatures.Length; i++)
                        {
                            Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M70H_CCD1_TEMP + (i * 0x4));
                            Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint ccdRawTemp);

                            ccdRawTemp &= 0xFFF;
                            float ccdTemp = ((ccdRawTemp * 125) - 305000) * 0.001f;
                            if (ccdRawTemp > 0 && ccdTemp < 125)  // Zen 2 reports 95 degrees C max, but it might exceed that.
                            {
                                if (_ccdTemperatures[i] == null)
                                {
                                    _cpu.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
                                                                                         _cpu._sensorTemperatures++,
                                                                                         SensorType.Temperature,
                                                                                         _cpu,
                                                                                         _cpu._settings));
                                }
                                _ccdTemperatures[i].Value = ccdTemp;
                            }
                        }

                        Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray();
                        if (activeCcds.Length > 1)
                        {
                            // No need to get the max / average ccds temp if there is only one CCD.

                            if (_ccdsMaxTemperature == null)
                            {
                                _cpu.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
                                                                                     _cpu._sensorTemperatures++,
                                                                                     SensorType.Temperature,
                                                                                     _cpu,
                                                                                     _cpu._settings));
                            }

                            if (_ccdsAverageTemperature == null)
                            {
                                _cpu.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
                                                                                         _cpu._sensorTemperatures++,
                                                                                         SensorType.Temperature,
                                                                                         _cpu,
                                                                                         _cpu._settings));
                            }

                            _ccdsMaxTemperature.Value     = activeCcds.Max(x => x.Value);
                            _ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value);
                        }
                    }
                    Ring0.ReleasePciBusMutex();
                }

                // voltage
                const double vidStep = 0.00625;
                double       vcc;
                uint         svi0PlaneXVddCor;

                // Core (0x01).
                if ((smuSvi0Tfn & 0x01) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane0 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _coreVoltage.Value = (float)vcc;

                    _cpu.ActivateSensor(_coreVoltage);
                }

                // SoC (0x02), not every Zen cpu has this voltage.
                if (cpuId.Model == 0x21 || cpuId.Model == 0x71 || cpuId.Model == 0x31 || (smuSvi0Tfn & 0x02) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane1 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _socVoltage.Value = (float)vcc;

                    _cpu.ActivateSensor(_socVoltage);
                }

                double timeStampCounterMultiplier = GetTimeStampCounterMultiplier();

                if (timeStampCounterMultiplier > 0)
                {
                    _busClock.Value = (float)(_cpu.TimeStampCounterFrequency / timeStampCounterMultiplier);
                    _cpu.ActivateSensor(_busClock);
                }
            }
        /// <summary>
        /// Initializes a new instance of the <see cref="CpuId" /> class.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="thread">The thread.</param>
        /// <param name="affinity">The affinity.</param>
        private CpuId(int group, int thread, GroupAffinity affinity)
        {
            Thread   = thread;
            Group    = group;
            Affinity = affinity;

            uint threadMaskWith;
            uint coreMaskWith;
            uint maxCpuidExt;

            if (thread >= 64)
            {
                throw new ArgumentOutOfRangeException(nameof(thread));
            }


            uint maxCpuid;

            if (OpCode.CpuId(CPUID_0, 0, out uint eax, out uint ebx, out uint ecx, out uint edx))
            {
                if (eax > 0)
                {
                    maxCpuid = eax;
                }
                else
                {
                    return;
                }


                StringBuilder vendorBuilder = new StringBuilder();
                AppendRegister(vendorBuilder, ebx);
                AppendRegister(vendorBuilder, edx);
                AppendRegister(vendorBuilder, ecx);
                string cpuVendor = vendorBuilder.ToString();

                switch (cpuVendor)
                {
                case "GenuineIntel":
                    Vendor = Vendor.Intel;
                    break;

                case "AuthenticAMD":
                    Vendor = Vendor.AMD;
                    break;

                default:
                    Vendor = Vendor.Unknown;
                    break;
                }

                if (OpCode.CpuId(CPUID_EXT, 0, out eax, out _, out _, out _))
                {
                    if (eax > CPUID_EXT)
                    {
                        maxCpuidExt = eax - CPUID_EXT;
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    throw new ArgumentOutOfRangeException(nameof(thread));
                }
            }
示例#9
0
 public static extern bool SetThreadGroupAffinity(IntPtr hThread, ref GroupAffinity groupAffinity, ref GroupAffinity prevAffinity);
示例#10
0
        private CPUID(int group, int thread, GroupAffinity affinity)
        {
            this.group    = group;
            this.thread   = thread;
            this.affinity = affinity;

            uint maxCpuid    = 0;
            uint maxCpuidExt = 0;

            uint eax, ebx, ecx, edx;

            Opcode.Cpuid(CPUID_0, 0, out eax, out ebx, out ecx, out edx);
            if (eax > 0)
            {
                maxCpuid = eax;
            }
            else
            {
                return;
            }

            StringBuilder vendorBuilder = new StringBuilder();

            AppendRegister(vendorBuilder, ebx);
            AppendRegister(vendorBuilder, edx);
            AppendRegister(vendorBuilder, ecx);
            string cpuVendor = vendorBuilder.ToString();

            switch (cpuVendor)
            {
            case "GenuineIntel":
                vendor = Vendor.Intel;
                break;

            case "AuthenticAMD":
                vendor = Vendor.AMD;
                break;

            default:
                vendor = Vendor.Unknown;
                break;
            }
            eax = ebx = ecx = edx = 0;
            Opcode.Cpuid(CPUID_EXT, 0, out eax, out ebx, out ecx, out edx);
            if (eax > CPUID_EXT)
            {
                maxCpuidExt = eax - CPUID_EXT;
            }
            else
            {
                return;
            }

            maxCpuid    = Math.Min(maxCpuid, 1024);
            maxCpuidExt = Math.Min(maxCpuidExt, 1024);

            cpuidData = new uint[maxCpuid + 1, 4];
            for (uint i = 0; i < (maxCpuid + 1); i++)
            {
                Opcode.Cpuid(CPUID_0 + i, 0,
                             out cpuidData[i, 0], out cpuidData[i, 1],
                             out cpuidData[i, 2], out cpuidData[i, 3]);
            }

            cpuidExtData = new uint[maxCpuidExt + 1, 4];
            for (uint i = 0; i < (maxCpuidExt + 1); i++)
            {
                Opcode.Cpuid(CPUID_EXT + i, 0,
                             out cpuidExtData[i, 0], out cpuidExtData[i, 1],
                             out cpuidExtData[i, 2], out cpuidExtData[i, 3]);
            }

            StringBuilder nameBuilder = new StringBuilder();

            for (uint i = 2; i <= 4; i++)
            {
                Opcode.Cpuid(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx);
                AppendRegister(nameBuilder, eax);
                AppendRegister(nameBuilder, ebx);
                AppendRegister(nameBuilder, ecx);
                AppendRegister(nameBuilder, edx);
            }
            nameBuilder.Replace('\0', ' ');
            cpuBrandString = nameBuilder.ToString().Trim();
            nameBuilder.Replace("Dual-Core Processor", "");
            nameBuilder.Replace("Triple-Core Processor", "");
            nameBuilder.Replace("Quad-Core Processor", "");
            nameBuilder.Replace("Six-Core Processor", "");
            nameBuilder.Replace("Eight-Core Processor", "");
            nameBuilder.Replace("Dual Core Processor", "");
            nameBuilder.Replace("Quad Core Processor", "");
            nameBuilder.Replace("12-Core Processor", "");
            nameBuilder.Replace("16-Core Processor", "");
            nameBuilder.Replace("24-Core Processor", "");
            nameBuilder.Replace("32-Core Processor", "");
            nameBuilder.Replace("64-Core Processor", "");
            nameBuilder.Replace("6-Core Processor", "");
            nameBuilder.Replace("8-Core Processor", "");
            nameBuilder.Replace("with Radeon Vega Mobile Gfx", "");
            nameBuilder.Replace("w/ Radeon Vega Mobile Gfx", "");
            nameBuilder.Replace("with Radeon Vega Graphics", "");
            nameBuilder.Replace("APU with Radeon(tm) HD Graphics", "");
            nameBuilder.Replace("APU with Radeon(TM) HD Graphics", "");
            nameBuilder.Replace("APU with AMD Radeon R2 Graphics", "");
            nameBuilder.Replace("APU with AMD Radeon R3 Graphics", "");
            nameBuilder.Replace("APU with AMD Radeon R4 Graphics", "");
            nameBuilder.Replace("APU with AMD Radeon R5 Graphics", "");
            nameBuilder.Replace("APU with Radeon(tm) R3", "");
            nameBuilder.Replace("RADEON R2, 4 COMPUTE CORES 2C+2G", "");
            nameBuilder.Replace("RADEON R4, 5 COMPUTE CORES 2C+3G", "");
            nameBuilder.Replace("RADEON R5, 5 COMPUTE CORES 2C+3G", "");
            nameBuilder.Replace("RADEON R5, 10 COMPUTE CORES 4C+6G", "");
            nameBuilder.Replace("RADEON R7, 10 COMPUTE CORES 4C+6G", "");
            nameBuilder.Replace("RADEON R7, 12 COMPUTE CORES 4C+8G", "");
            nameBuilder.Replace("Radeon R5, 6 Compute Cores 2C+4G", "");
            nameBuilder.Replace("Radeon R5, 8 Compute Cores 4C+4G", "");
            nameBuilder.Replace("Radeon R6, 10 Compute Cores 4C+6G", "");
            nameBuilder.Replace("Radeon R7, 10 Compute Cores 4C+6G", "");
            nameBuilder.Replace("Radeon R7, 12 Compute Cores 4C+8G", "");
            nameBuilder.Replace("R5, 10 Compute Cores 4C+6G", "");
            nameBuilder.Replace("R7, 12 COMPUTE CORES 4C+8G", "");
            nameBuilder.Replace("(R)", " ");
            nameBuilder.Replace("(TM)", " ");
            nameBuilder.Replace("(tm)", " ");
            nameBuilder.Replace("CPU", " ");

            for (int i = 0; i < 10; i++)
            {
                nameBuilder.Replace("  ", " ");
            }
            name = nameBuilder.ToString();
            if (name.Contains("@"))
            {
                name = name.Remove(name.LastIndexOf('@'));
            }
            name = name.Trim();

            this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
                          ((cpuidData[1, 0] & 0x0F00) >> 8);
            this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
                         ((cpuidData[1, 0] & 0xF0) >> 4);
            this.stepping = (cpuidData[1, 0] & 0x0F);

            this.apicId = (cpuidData[1, 1] >> 24) & 0xFF;

            switch (vendor)
            {
            case Vendor.Intel:
                uint maxCoreAndThreadIdPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
                uint maxCoreIdPerPackage;
                if (maxCpuid >= 4)
                {
                    maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
                }
                else
                {
                    maxCoreIdPerPackage = 1;
                }
                threadMaskWith =
                    NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage);
                coreMaskWith = NextLog2(maxCoreIdPerPackage);
                break;

            case Vendor.AMD:
                if (this.family == 0x17)
                {
                    coreMaskWith   = (cpuidExtData[8, 2] >> 12) & 0xF;
                    threadMaskWith =
                        NextLog2(((cpuidExtData[0x1E, 1] >> 8) & 0xFF) + 1);
                }
                else
                {
                    uint corePerPackage;
                    if (maxCpuidExt >= 8)
                    {
                        corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
                    }
                    else
                    {
                        corePerPackage = 1;
                    }
                    coreMaskWith   = NextLog2(corePerPackage);
                    threadMaskWith = 0;
                }
                break;

            default:
                threadMaskWith = 0;
                coreMaskWith   = 0;
                break;
            }

            processorId = (apicId >> (int)(coreMaskWith + threadMaskWith));
            coreId      = ((apicId >> (int)(threadMaskWith))
                           - (processorId << (int)(coreMaskWith)));
            threadId = apicId
                       - (processorId << (int)(coreMaskWith + threadMaskWith))
                       - (coreId << (int)(threadMaskWith));
        }
        public GenericCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(cpuId[0][0].Name, CreateIdentifier(cpuId[0][0].Vendor, processorIndex), settings)
        {
            _cpuId       = cpuId;
            _vendor      = cpuId[0][0].Vendor;
            _family      = cpuId[0][0].Family;
            _model       = cpuId[0][0].Model;
            _stepping    = cpuId[0][0].Stepping;
            _packageType = cpuId[0][0].PkgType;

            Index        = processorIndex;
            _coreCount   = cpuId.Length;
            _threadCount = cpuId.Sum(x => x.Length);

            // Check if processor has MSRs.
            HasModelSpecificRegisters = cpuId[0][0].Data.GetLength(0) > 1 && (cpuId[0][0].Data[1, 3] & 0x20) != 0;

            // Check if processor has a TSC.
            HasTimeStampCounter = cpuId[0][0].Data.GetLength(0) > 1 && (cpuId[0][0].Data[1, 3] & 0x10) != 0;

            // Check if processor supports an invariant TSC.
            _isInvariantTimeStampCounter = cpuId[0][0].ExtData.GetLength(0) > 7 && (cpuId[0][0].ExtData[7, 3] & 0x100) != 0;

            _totalLoad = _coreCount > 1 ? new Sensor("CPU Total", 0, SensorType.Load, this, settings) : null;

            _cpuLoad = new CpuLoad(cpuId);
            if (_cpuLoad.IsAvailable)
            {
                _threadLoads = new Sensor[_threadCount];
                for (int coreIdx = 0; coreIdx < cpuId.Length; coreIdx++)
                {
                    for (int threadIdx = 0; threadIdx < cpuId[coreIdx].Length; threadIdx++)
                    {
                        int thread = cpuId[coreIdx][threadIdx].Thread;
                        if (thread < _threadLoads.Length)
                        {
                            // Some cores may have 2 threads while others have only one (e.g. P-cores vs E-cores on Intel 12th gen).
                            string sensorName = CoreString(coreIdx) + (cpuId[coreIdx].Length > 1 ? $" Thread #{threadIdx + 1}" : string.Empty);
                            _threadLoads[thread] = new Sensor(sensorName, thread + 1, SensorType.Load, this, settings);

                            ActivateSensor(_threadLoads[thread]);
                        }
                    }
                }

                if (_totalLoad != null)
                {
                    ActivateSensor(_totalLoad);
                }
            }

            if (HasTimeStampCounter)
            {
                GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId[0][0].Affinity);
                EstimateTimeStampCounterFrequency(out _estimatedTimeStampCounterFrequency, out _estimatedTimeStampCounterFrequencyError);
                ThreadAffinity.Set(previousAffinity);
            }
            else
            {
                _estimatedTimeStampCounterFrequency = 0;
            }

            TimeStampCounterFrequency = _estimatedTimeStampCounterFrequency;
        }
示例#12
0
        public GenericCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(cpuId[0][0].Name, CreateIdentifier(cpuId[0][0].Vendor, processorIndex), settings)
        {
            _cpuId       = cpuId;
            _vendor      = cpuId[0][0].Vendor;
            _family      = cpuId[0][0].Family;
            _model       = cpuId[0][0].Model;
            _stepping    = cpuId[0][0].Stepping;
            _packageType = cpuId[0][0].PkgType;

            Index      = processorIndex;
            _coreCount = cpuId.Length;

            // check if processor has MSRs
            if (cpuId[0][0].Data.GetLength(0) > 1 && (cpuId[0][0].Data[1, 3] & 0x20) != 0)
            {
                HasModelSpecificRegisters = true;
            }
            else
            {
                HasModelSpecificRegisters = false;
            }

            // check if processor has a TSC
            if (cpuId[0][0].Data.GetLength(0) > 1 && (cpuId[0][0].Data[1, 3] & 0x10) != 0)
            {
                HasTimeStampCounter = true;
            }
            else
            {
                HasTimeStampCounter = false;
            }

            // check if processor supports an invariant TSC
            if (cpuId[0][0].ExtData.GetLength(0) > 7 && (cpuId[0][0].ExtData[7, 3] & 0x100) != 0)
            {
                _isInvariantTimeStampCounter = true;
            }
            else
            {
                _isInvariantTimeStampCounter = false;
            }

            _totalLoad = _coreCount > 1 ? new Sensor("CPU Total", 0, SensorType.Load, this, settings) : null;

            _coreLoads = new Sensor[_coreCount];
            for (int i = 0; i < _coreLoads.Length; i++)
            {
                _coreLoads[i] = new Sensor(CoreString(i), i + 1, SensorType.Load, this, settings);
            }

            _cpuLoad = new CpuLoad(cpuId);
            if (_cpuLoad.IsAvailable)
            {
                foreach (Sensor sensor in _coreLoads)
                {
                    ActivateSensor(sensor);
                }

                if (_totalLoad != null)
                {
                    ActivateSensor(_totalLoad);
                }
            }

            if (HasTimeStampCounter)
            {
                GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId[0][0].Affinity);
                EstimateTimeStampCounterFrequency(out _estimatedTimeStampCounterFrequency, out _estimatedTimeStampCounterFrequencyError);
                ThreadAffinity.Set(previousAffinity);
            }
            else
            {
                _estimatedTimeStampCounterFrequency = 0;
            }

            TimeStampCounterFrequency = _estimatedTimeStampCounterFrequency;
        }