OSDN Git Service

Moved the CPU detection code into the MUtils library.
authorLoRd_MuldeR <mulder2@gmx.de>
Tue, 25 Nov 2014 02:16:45 +0000 (03:16 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Tue, 25 Nov 2014 02:16:45 +0000 (03:16 +0100)
MUtilities_VS2013.vcxproj
MUtilities_VS2013.vcxproj.filters
include/MUtils/CPUFeatures.h [new file with mode: 0644]
include/MUtils/Version.h
src/CPUFeatures_Win32.cpp [new file with mode: 0644]

index 794fdc5..5109d15 100644 (file)
@@ -15,6 +15,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="src\CPUFeatures_Win32.cpp" />
     <ClCompile Include="src\Global.cpp" />
     <ClCompile Include="src\KeccakHash.cpp" />
     <ClCompile Include="src\OSSupport_Win32.cpp" />
@@ -23,6 +24,7 @@
     <ClCompile Include="tmp\MUtilities_VS2013\MOC_UpdateChecker.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="include\MUtils\CPUFeatures.h" />
     <ClInclude Include="include\MUtils\Exception.h" />
     <ClInclude Include="include\MUtils\Global.h" />
     <ClInclude Include="include\MUtils\KeccakHash.h" />
index e231689..d48f878 100644 (file)
@@ -39,6 +39,9 @@
     <ClCompile Include="src\KeccakHash.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\CPUFeatures_Win32.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\CriticalSection_Win32.h">
@@ -62,6 +65,9 @@
     <ClInclude Include="src\DirLocker.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="include\MUtils\CPUFeatures.h">
+      <Filter>Public Headers</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
diff --git a/include/MUtils/CPUFeatures.h b/include/MUtils/CPUFeatures.h
new file mode 100644 (file)
index 0000000..ac70201
--- /dev/null
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+//MUtils
+#include <MUtils/Global.h>
+
+//Qt
+#include <QStringList>
+
+namespace MUtils
+{
+       namespace CPUFetaures
+       {
+               //CPU flags
+               static const quint32 FLAG_MMX   = 0x01;
+               static const quint32 FLAG_SSE   = 0x02;
+               static const quint32 FLAG_SSE2  = 0x04;
+               static const quint32 FLAG_SSE3  = 0x08;
+               static const quint32 FLAG_SSSE3 = 0x10;
+               static const quint32 FLAG_SSE4  = 0x20;
+               static const quint32 FLAG_SSE42 = 0x40;
+
+               //CPU features
+               typedef struct _cpu_info_t
+               {
+                       quint32 family;
+                       quint32 model;
+                       quint32 stepping;
+                       quint32 count;
+                       quint32 features;
+                       bool x64;
+                       bool intel;
+                       char vendor[0x40];
+                       char brand[0x40];
+               }
+               cpu_info_t;
+
+               MUTILS_API cpu_info_t detect(const QStringList &argv);
+       }
+}
index a0d9e7f..8e47a62 100644 (file)
@@ -41,7 +41,7 @@ namespace MUtils
                MUTILS_API static const QTime build_time(const char *const time_str = build_time_raw());
 
                //Compiler detection
-               MUTILS_API static const char *const compiler_version(void)
+               static const char *const compiler_version(void)
                {
                        #if defined(__INTEL_COMPILER)
                                #if (__INTEL_COMPILER >= 1500)
@@ -109,7 +109,7 @@ namespace MUtils
                }
 
                //Architecture detection
-               MUTILS_API static const char *const compiler_arch(void)
+               static const char *const compiler_arch(void)
                {
                        #if defined(_M_X64)
                                static const char *const COMPILER_ARCH = "x64";
diff --git a/src/CPUFeatures_Win32.cpp b/src/CPUFeatures_Win32.cpp
new file mode 100644 (file)
index 0000000..fe45cdb
--- /dev/null
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+//Win32 API
+#define WIN32_LEAN_AND_MEAN 1
+#include <Windows.h>
+
+//MUtils
+#include <MUtils/CPUFeatures.h>
+
+//Qt
+#include <QLibrary>
+
+MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(const QStringList &argv)
+{
+       typedef BOOL (WINAPI *IsWow64ProcessFun)(__in HANDLE hProcess, __out PBOOL Wow64Process);
+
+       cpu_info_t features;
+       SYSTEM_INFO systemInfo;
+       int CPUInfo[4] = {-1};
+       char CPUIdentificationString[0x40];
+       char CPUBrandString[0x40];
+
+       memset(&features, 0, sizeof(cpu_info_t));
+       memset(&systemInfo, 0, sizeof(SYSTEM_INFO));
+       memset(CPUIdentificationString, 0, sizeof(CPUIdentificationString));
+       memset(CPUBrandString, 0, sizeof(CPUBrandString));
+       
+       __cpuid(CPUInfo, 0);
+       memcpy(CPUIdentificationString, &CPUInfo[1], sizeof(int));
+       memcpy(CPUIdentificationString + 4, &CPUInfo[3], sizeof(int));
+       memcpy(CPUIdentificationString + 8, &CPUInfo[2], sizeof(int));
+       features.intel = (_stricmp(CPUIdentificationString, "GenuineIntel") == 0);
+       strncpy_s(features.vendor, 0x40, CPUIdentificationString, _TRUNCATE);
+
+       if(CPUInfo[0] >= 1)
+       {
+               __cpuid(CPUInfo, 1);
+               if(CPUInfo[3] & 0x00800000) features.features |= FLAG_MMX;
+               if(CPUInfo[3] & 0x02000000) features.features |= FLAG_SSE;
+               if(CPUInfo[3] & 0x04000000) features.features |= FLAG_SSE2;
+               if(CPUInfo[2] & 0x00000001) features.features |= FLAG_SSE3;
+               if(CPUInfo[2] & 0x00000200) features.features |= FLAG_SSSE3;
+               if(CPUInfo[2] & 0x00080000) features.features |= FLAG_SSE4;
+               if(CPUInfo[2] & 0x00100000) features.features |= FLAG_SSE42;
+               features.stepping = CPUInfo[0] & 0xf;
+               features.model    = ((CPUInfo[0] >> 4) & 0xf) + (((CPUInfo[0] >> 16) & 0xf) << 4);
+               features.family   = ((CPUInfo[0] >> 8) & 0xf) + ((CPUInfo[0] >> 20) & 0xff);
+       }
+
+       __cpuid(CPUInfo, 0x80000000);
+       int nExIds = qMax<int>(qMin<int>(CPUInfo[0], 0x80000004), 0x80000000);
+
+       for(int i = 0x80000002; i <= nExIds; ++i)
+       {
+               __cpuid(CPUInfo, i);
+               switch(i)
+               {
+               case 0x80000002:
+                       memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
+                       break;
+               case 0x80000003:
+                       memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
+                       break;
+               case 0x80000004:
+                       memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
+                       break;
+               }
+       }
+
+       strncpy_s(features.brand, 0x40, CPUBrandString, _TRUNCATE);
+
+       if(strlen(features.brand)  < 1) strncpy_s(features.brand,  0x40, "Unknown", _TRUNCATE);
+       if(strlen(features.vendor) < 1) strncpy_s(features.vendor, 0x40, "Unknown", _TRUNCATE);
+
+#if (!(defined(_M_X64) || defined(_M_IA64)))
+       QLibrary Kernel32Lib("kernel32.dll");
+       if(IsWow64ProcessFun IsWow64ProcessPtr = (IsWow64ProcessFun) Kernel32Lib.resolve("IsWow64Process"))
+       {
+               BOOL x64flag = FALSE;
+               if(IsWow64ProcessPtr(GetCurrentProcess(), &x64flag))
+               {
+                       features.x64 = (x64flag == TRUE);
+               }
+       }
+#else
+       features.x64 = true;
+#endif
+
+       DWORD_PTR procAffinity, sysAffinity;
+       if(GetProcessAffinityMask(GetCurrentProcess(), &procAffinity, &sysAffinity))
+       {
+               for(DWORD_PTR mask = 1; mask; mask <<= 1)
+               {
+                       features.count += ((sysAffinity & mask) ? (1) : (0));
+               }
+       }
+       if(features.count < 1)
+       {
+               GetNativeSystemInfo(&systemInfo);
+               features.count = qBound(1UL, systemInfo.dwNumberOfProcessors, 64UL);
+       }
+
+       if(argv.count() > 0)
+       {
+               bool flag = false;
+               for(int i = 0; i < argv.count(); i++)
+               {
+                       if(!argv[i].compare("--force-cpu-no-64bit", Qt::CaseInsensitive)) { flag = true; features.x64 = false; }
+                       if(!argv[i].compare("--force-cpu-no-sse",   Qt::CaseInsensitive)) { flag = true; features.features &= (~(FLAG_SSE | FLAG_SSE2 | FLAG_SSE3 | FLAG_SSSE3 | FLAG_SSE4 | FLAG_SSE42)); }
+                       if(!argv[i].compare("--force-cpu-no-intel", Qt::CaseInsensitive)) { flag = true; features.intel = false; }
+               }
+               if(flag) qWarning("CPU flags overwritten by user-defined parameters. Take care!\n");
+       }
+
+       return features;
+}