Hardware/CPU/CPUGroup.cs
author moel.mich
Sat, 27 Oct 2012 11:40:28 +0000
changeset 384 76f859f4aea1
parent 301 d14ce71cef44
child 407 c9dfdbd59bf8
permissions -rw-r--r--
Reduced the amount of dynamic memory allocation when reading from the T-Balancer or creating tray icons.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Collections.Generic;
    13 using System.Globalization;
    14 using System.Text;
    15 
    16 namespace OpenHardwareMonitor.Hardware.CPU {
    17 
    18   internal class CPUGroup : IGroup {
    19     private readonly List<GenericCPU> hardware = new List<GenericCPU>();
    20 
    21     private readonly CPUID[][][] threads;
    22 
    23     private static CPUID[][] GetProcessorThreads() {
    24 
    25       List<CPUID> threads = new List<CPUID>();
    26       for (int i = 0; i < 32; i++) {
    27         try {
    28           threads.Add(new CPUID(i));
    29         } catch (ArgumentOutOfRangeException) { }
    30       }
    31 
    32       SortedDictionary<uint, List<CPUID>> processors =
    33         new SortedDictionary<uint, List<CPUID>>();
    34       foreach (CPUID thread in threads) {
    35         List<CPUID> list;
    36         processors.TryGetValue(thread.ProcessorId, out list);
    37         if (list == null) {
    38           list = new List<CPUID>();
    39           processors.Add(thread.ProcessorId, list);
    40         }
    41         list.Add(thread);
    42       }
    43 
    44       CPUID[][] processorThreads = new CPUID[processors.Count][];
    45       int index = 0;
    46       foreach (List<CPUID> list in processors.Values) {
    47         processorThreads[index] = list.ToArray();
    48         index++;
    49       }
    50       return processorThreads;
    51     }
    52 
    53     private static CPUID[][] GroupThreadsByCore(IEnumerable<CPUID> threads) {
    54 
    55       SortedDictionary<uint, List<CPUID>> cores = 
    56         new SortedDictionary<uint, List<CPUID>>();
    57       foreach (CPUID thread in threads) {
    58         List<CPUID> coreList;
    59         cores.TryGetValue(thread.CoreId, out coreList);
    60         if (coreList == null) {
    61           coreList = new List<CPUID>();
    62           cores.Add(thread.CoreId, coreList);
    63         }
    64         coreList.Add(thread);
    65       }
    66 
    67       CPUID[][] coreThreads = new CPUID[cores.Count][];
    68       int index = 0;
    69       foreach (List<CPUID> list in cores.Values) {
    70         coreThreads[index] = list.ToArray();
    71         index++;
    72       }
    73       return coreThreads;
    74     }
    75 
    76     public CPUGroup(ISettings settings) {
    77 
    78       CPUID[][] processorThreads = GetProcessorThreads();
    79       this.threads = new CPUID[processorThreads.Length][][];
    80 
    81       int index = 0;
    82       foreach (CPUID[] threads in processorThreads) {
    83         if (threads.Length == 0)
    84           continue;
    85             
    86         CPUID[][] coreThreads = GroupThreadsByCore(threads);
    87 
    88         this.threads[index] = coreThreads;
    89 
    90         switch (threads[0].Vendor) {
    91           case Vendor.Intel:
    92             hardware.Add(new IntelCPU(index, coreThreads, settings));
    93             break;
    94           case Vendor.AMD:
    95             switch (threads[0].Family) {
    96               case 0x0F:
    97                 hardware.Add(new AMD0FCPU(index, coreThreads, settings));
    98                 break;
    99               case 0x10:
   100               case 0x11:
   101               case 0x12:
   102               case 0x14:
   103               case 0x15:
   104                 hardware.Add(new AMD10CPU(index, coreThreads, settings));
   105                 break;
   106               default:
   107                 hardware.Add(new GenericCPU(index, coreThreads, settings));
   108                 break;
   109             } break;
   110           default:
   111             hardware.Add(new GenericCPU(index, coreThreads, settings));
   112             break;
   113         }
   114 
   115         index++;
   116       }
   117     }
   118     
   119     public IHardware[] Hardware {
   120       get {
   121         return hardware.ToArray();
   122       }
   123     }
   124 
   125     private static void AppendCpuidData(StringBuilder r, uint[,] data, 
   126       uint offset) 
   127     {
   128       for (int i = 0; i < data.GetLength(0); i++) {
   129         r.Append(" ");
   130         r.Append((i + offset).ToString("X8", CultureInfo.InvariantCulture));
   131         for (int j = 0; j < 4; j++) {
   132           r.Append("  ");
   133           r.Append(data[i, j].ToString("X8", CultureInfo.InvariantCulture));
   134         }
   135         r.AppendLine();
   136       }
   137     }
   138 
   139     public string GetReport() {
   140       if (threads == null)
   141         return null;
   142       
   143       StringBuilder r = new StringBuilder();
   144       
   145       r.AppendLine("CPUID");
   146       r.AppendLine();
   147 
   148       for (int i = 0; i < threads.Length; i++) {
   149 
   150         r.AppendLine("Processor " + i);
   151         r.AppendLine();
   152         r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor,
   153           Environment.NewLine);
   154         r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString,
   155           Environment.NewLine);
   156         r.AppendFormat("Family: 0x{0}{1}", 
   157           threads[i][0][0].Family.ToString("X", CultureInfo.InvariantCulture), 
   158           Environment.NewLine);
   159         r.AppendFormat("Model: 0x{0}{1}",
   160           threads[i][0][0].Model.ToString("X", CultureInfo.InvariantCulture), 
   161           Environment.NewLine);
   162         r.AppendFormat("Stepping: 0x{0}{1}",
   163           threads[i][0][0].Stepping.ToString("X", CultureInfo.InvariantCulture), 
   164           Environment.NewLine);
   165         r.AppendLine();
   166 
   167         r.AppendLine("CPUID Return Values");
   168         r.AppendLine();
   169         for (int j = 0; j < threads[i].Length; j++)
   170           for (int k = 0; k < threads[i][j].Length; k++) {
   171             r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread);
   172             r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
   173             r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);
   174             r.AppendLine(" Core ID: " + threads[i][j][k].CoreId);
   175             r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId);
   176             r.AppendLine();
   177             r.AppendLine(" Function  EAX       EBX       ECX       EDX");
   178             AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0);
   179             AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT);
   180             r.AppendLine();
   181           }
   182       }
   183       return r.ToString(); 
   184     }
   185 
   186     public void Close() {
   187       foreach (GenericCPU cpu in hardware) {
   188         cpu.Close();
   189       }
   190     }
   191   }
   192 }