nux-1.16.0
CPU.cpp
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "NuxCore.h"
00024 
00025 #ifdef _WIN32
00026 #include <intrin.h>
00027 
00028 namespace nux
00029 {
00030 
00031   NUX_IMPLEMENT_GLOBAL_OBJECT (NCPU);
00032 
00033 //============================================================================
00034 // Calculate and log the amount of RAM in the machine
00035 //============================================================================
00036   static t_u64 GetTotalPhysRAM_MB()
00037   {
00038     // Get memory status
00039     MEMORYSTATUSEX theStatus;
00040     ZeroMemory (&theStatus, sizeof (theStatus) );
00041     theStatus.dwLength = sizeof (theStatus);
00042     GlobalMemoryStatusEx (&theStatus);
00043 
00044     return theStatus.ullTotalPhys / (1024 * 1024);
00045   }
00046 
00047 //============================================================================
00048 // Read the CPU speed from the registry
00049 //============================================================================
00050   static DWORD GetCPUSpeedFromRegistry (DWORD dwCPU)
00051   {
00052     HKEY hKey;
00053     DWORD dwSpeed;
00054 
00055     // Get the key name
00056     TCHAR szKey[256];
00057     _sntprintf_s (szKey, 256, sizeof (szKey) / sizeof (wchar_t), TEXT ("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d\\"), dwCPU);
00058 
00059     // Open the key
00060     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
00061     {
00062       return 0;
00063     }
00064 
00065     // Read the value
00066     DWORD dwLen = 4;
00067 
00068     if (RegQueryValueEx (hKey, TEXT ("~MHz"), NULL, NULL, (LPBYTE) &dwSpeed, &dwLen) != ERROR_SUCCESS)
00069     {
00070       RegCloseKey (hKey);
00071       return 0;
00072     }
00073 
00074     // Cleanup and return
00075     RegCloseKey (hKey);
00076     return dwSpeed;
00077   }
00078 
00079   void NCPU::Constructor()
00080   {
00081     unsigned nHighestFeature;
00082     unsigned nHighestFeatureEx;
00083     int nBuff[4];
00084     char szMan[13];
00085 
00086     Memset (&m_CPUInfo, 0, sizeof (m_CPUInfo) );
00087     Memset (&m_CPUFeatures, 0, sizeof (m_CPUFeatures) );
00088 
00089     // Get CPU manufacturer and highest CPUID
00090     __cpuid (nBuff, 0);
00091 
00092     nHighestFeature = (unsigned) nBuff[0];
00093     * (int *) &szMan[0] = nBuff[1];
00094     * (int *) &szMan[4] = nBuff[3];
00095     * (int *) &szMan[8] = nBuff[2];
00096     szMan[12] = 0;
00097 
00098     if (strcmp (szMan, "AuthenticAMD") == 0)
00099     {
00100       m_CPUInfo.m_CPUType = CPU_AMD;
00101     }
00102     else if (strcmp (szMan, "GenuineIntel") == 0)
00103     {
00104       m_CPUInfo.m_CPUType = CPU_INTEL;
00105     }
00106     else
00107     {
00108       m_CPUInfo.m_CPUType = CPU_UNKNOWN;
00109     }
00110 
00111     m_CPUString = szMan;
00112 
00113     // Get highest extended feature
00114     __cpuid (nBuff, 0x80000000);
00115     nHighestFeatureEx = (unsigned) nBuff[0];
00116 
00117     // Get processor brand name
00118     if (nHighestFeatureEx >= 0x80000004)
00119     {
00120       char szCPUName[49];
00121       szCPUName[0] = 0;
00122       __cpuid ( (int *) &szCPUName[0], 0x80000002);
00123       __cpuid ( (int *) &szCPUName[16], 0x80000003);
00124       __cpuid ( (int *) &szCPUName[32], 0x80000004);
00125       szCPUName[48] = 0;
00126 
00127       m_CPUBrandString = szCPUName;
00128 //         for(int i=(int)strlen(szCPUName)-1; i>=0; --i)
00129 //         {
00130 //             if(szCPUName[i] == ' ')
00131 //                 szCPUName[i] = '\0';
00132 //             else
00133 //                 break;
00134 //         }
00135     }
00136 
00137     // Get CPU features
00138     if (nHighestFeature >= 1)
00139     {
00140       __cpuid (nBuff, 1);
00141 
00142 
00143       m_CPUInfo.m_CPUSteppingID = nBuff[0] & 0xf;
00144       m_CPUInfo.m_CPUModel = (nBuff[0] >> 4) & 0xf;
00145       m_CPUInfo.m_CPUFamily = (nBuff[0] >> 8) & 0xf;
00146       //m_CPUInfo.nProcessorType = (nBuff[0] >> 12) & 0x3;
00147       m_CPUInfo.m_CPUExtModel = (nBuff[0] >> 16) & 0xf;
00148       m_CPUInfo.m_CPUExtFamily = (nBuff[0] >> 20) & 0xff;
00149       //nBrandIndex = nBuff[1] & 0xff;
00150       m_CPUInfo.m_CPUNumLogicalProcessors = ( (nBuff[1] >> 16) & 0xff);
00151 
00152 
00153 
00154 
00155       if (nBuff[3] & 1 << 0)
00156         m_CPUFeatures.m_HasFPU = true;
00157 
00158       if (nBuff[3] & 1 << 23)
00159         m_CPUFeatures.m_HasMMX = true;
00160 
00161       if (nBuff[3] & 1 << 25)
00162         m_CPUFeatures.m_HasSSE = true;
00163 
00164       if (nBuff[3] & 1 << 26)
00165         m_CPUFeatures.m_HasSSE2 = true;
00166 
00167       if (nBuff[2] & 1 << 0)
00168         m_CPUFeatures.m_HasSSE3 = true;
00169 
00170       if (nBuff[2] & 1 << 19)
00171         m_CPUFeatures.m_HasSSE41 = true;
00172 
00173       if (nBuff[2] & 1 << 20)
00174         m_CPUFeatures.m_HasSSE42 = true;
00175 
00176       // Intel specific:
00177       if (m_CPUInfo.m_CPUType == CPU_INTEL)
00178       {
00179         if (nBuff[2] & 1 << 9)
00180           m_CPUFeatures.m_HasSSSE3 = true;
00181 
00182         if (nBuff[2] & 1 << 7)
00183           m_CPUFeatures.m_HasEST = true;
00184       }
00185 
00186       if (nBuff[3] & 1 << 28)
00187         m_CPUFeatures.m_HasHTT = true;
00188     }
00189 
00190     // AMD specific:
00191     if (m_CPUInfo.m_CPUType == CPU_AMD)
00192     {
00193       // Get extended features
00194       __cpuid (nBuff, 0x80000000);
00195 
00196       if (nHighestFeatureEx >= 0x80000001)
00197       {
00198         __cpuid (nBuff, 0x80000001);
00199 
00200         if (nBuff[3] & 1 << 31)
00201           m_CPUFeatures.m_Has3DNow = true;
00202 
00203         if (nBuff[3] & 1 << 30)
00204           m_CPUFeatures.m_Has3DNowExt = true;
00205 
00206         if (nBuff[3] & 1 << 22)
00207           m_CPUFeatures.m_HasAMDMMX = true;
00208       }
00209 
00210 //         // Get level 1 cache size
00211 //         if(nHighestFeatureEx >= 0x80000005)
00212 //         {
00213 //             __cpuid(nBuff, 0x80000005);
00214 //             ELog::Get().SystemFormat(L"PERF    : L1 cache size: %dK\n", ((unsigned)nBuff[2])>>24);
00215 //         }
00216     }
00217 
00218     if (nHighestFeatureEx >= 0x80000001)
00219     {
00220       __cpuid (nBuff, 0x80000001);
00221 
00222       if (nBuff[3] & 1 << 29)
00223         m_CPUFeatures.m_Hasx64 = true;
00224 
00225     }
00226 
00227     m_CPUInfo.m_CPUSpeed = GetCPUSpeedFromRegistry (0);
00228     m_MemInfo.m_PhysicalMemorySize = GetTotalPhysRAM_MB();
00229     GetOS();
00230 
00231     unsigned int dw = 0x00000001;
00232     m_IsLittleEndian = (* ( (char *) &dw ) ? true : false);
00233 
00234     //m_MemInfo
00235 //     // Get cache size
00236 //     if(nHighestFeatureEx >= 0x80000006)
00237 //     {
00238 //         __cpuid(nBuff, 0x80000006);
00239 //         ELog::Get().SystemFormat(L"PERF    : L2 cache size: %dK\n", ((unsigned)nBuff[2])>>16);
00240 //     }
00241 //
00242 //     // Log features
00243 //     ELog::Get().SystemFormat(L"PERF    : CPU Features: %S\n", szFeatures);
00244 //
00245 //     // Get misc system info
00246 //     SYSTEM_INFO theInfo;
00247 //     GetSystemInfo(&theInfo);
00248 //
00249 //     // Log number of CPUs and speeds
00250 //     ELog::Get().SystemFormat(L"PERF    : Number of CPUs: %d\n", theInfo.dwNumberOfProcessors);
00251 //     for(DWORD i=0; i<theInfo.dwNumberOfProcessors; ++i)
00252 //     {
00253 //         DWORD dwCPUSpeed = ReadCPUSpeedFromRegistry(i);
00254 //         ELog::Get().SystemFormat(L"PERF    : * CPU %d speed: ~%dMHz\n", i, dwCPUSpeed);
00255 //     }
00256   }
00257 
00258 
00259   void NCPU::Destructor()
00260   {
00261 
00262   }
00263 
00264   typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
00265   LPFN_ISWOW64PROCESS fnIsWow64Process;
00266 
00267 
00268 //============================================================================
00269 // Determine OS type
00270 //============================================================================
00271   void NCPU::GetOS()
00272   {
00273     void *ptr = 0;
00274     int PointerSize = sizeof (ptr);
00275     OSVERSIONINFOEX osInfo;
00276     SYSTEM_INFO sysInfo;
00277 
00278     // Get system info
00279     ZeroMemory (&sysInfo, sizeof (sysInfo) );
00280     GetSystemInfo (&sysInfo);
00281 
00282     // Get OS version
00283     ZeroMemory (&osInfo, sizeof (osInfo) );
00284     osInfo.dwOSVersionInfoSize = sizeof (osInfo);
00285 
00286     if (!GetVersionEx ( (OSVERSIONINFO *) &osInfo) )
00287     {
00288       ZeroMemory (&osInfo, sizeof (osInfo) );
00289       osInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00290       GetVersionEx ( (OSVERSIONINFO *) &osInfo);
00291     }
00292 
00293     // Win 9x
00294     if (osInfo.dwPlatformId == 1)
00295     {
00296       if ( (osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 0) )
00297         m_OSInfo.m_OSType = OS_WIN95;
00298       else if ( (osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 10) )
00299         m_OSInfo.m_OSType = OS_WIN98;
00300       else if ( (osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 90) )
00301         m_OSInfo.m_OSType = OS_WINME;
00302       else
00303         m_OSInfo.m_OSType = OS_UNKNOWN;
00304     }
00305 
00306     // Win NT
00307     else if (osInfo.dwPlatformId == 2)
00308     {
00309       if ( (osInfo.dwMajorVersion == 4) && (osInfo.dwMinorVersion == 0) )
00310       {
00311         m_OSInfo.m_OSType = OS_WINNT40;
00312       }
00313       else if ( (osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 0) )
00314       {
00315         m_OSInfo.m_OSType = OS_WIN2000;
00316       }
00317       else if ( (osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 1) )
00318       {
00319         m_OSInfo.m_OSType = OS_WINXP;
00320       }
00321       else if ( (osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion == 2) )
00322       {
00323         if (GetSystemMetrics (89) )     // SM_SERVERR2 == 89
00324         {
00325           m_OSInfo.m_OSType = OS_WINSERVER2003R2;
00326         }
00327         else if ( (osInfo.wProductType == VER_NT_WORKSTATION) &&
00328                   (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) )
00329         {
00330           m_OSInfo.m_OSType = OS_WINXP64;
00331         }
00332         else
00333         {
00334           m_OSInfo.m_OSType = OS_WINSERVER2003;
00335         }
00336       }
00337       else if ( (osInfo.dwMajorVersion == 6) && (osInfo.dwMinorVersion == 0) )
00338       {
00339         m_OSInfo.m_OSType = OS_WINVISTA;
00340         BOOL bIsWow64 = FALSE;
00341         fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (TEXT ("kernel32") ), "IsWow64Process");
00342 
00343         if (fnIsWow64Process != NULL)
00344         {
00345           if (!fnIsWow64Process (GetCurrentProcess(), &bIsWow64) )
00346           {
00347             // handle error
00348             nuxCriticalMsg(TEXT("[NCPU::GetOS] Failed to getOS info."));
00349             return;
00350           }
00351         }
00352 
00353         if ( (PointerSize == 4) && bIsWow64)
00354         {
00355           // This is Vista 64 bits
00356           m_OSInfo.m_OSType = OS_WINVISTA64;
00357         }
00358 
00359         if (PointerSize == 8)
00360         {
00361           // This is Vista 64 bits
00362           m_OSInfo.m_OSType = OS_WINVISTA64;
00363         }
00364       }
00365       else
00366       {
00367         m_OSInfo.m_OSType = OS_UNKNOWN;
00368       }
00369     }
00370     else
00371     {
00372       m_OSInfo.m_OSType = OS_UNKNOWN;
00373     }
00374   }
00375 
00376   bool NCPU::IsBigEndian()
00377   {
00378     return !m_IsLittleEndian;
00379   }
00380 
00381   bool NCPU::IsLittleEndian()
00382   {
00383     return m_IsLittleEndian;
00384   }
00385 
00386 }
00387 
00388 #endif // _WIN32
00389 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends