nux-1.16.0
|
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