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); }
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(); } } }
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(); } } }
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); } }
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); } } }
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)); } }
public static extern bool SetThreadGroupAffinity(IntPtr hThread, ref GroupAffinity groupAffinity, ref GroupAffinity prevAffinity);
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; }
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; }