Status PerfCounterCollector::open() { PDH_STATUS status = PdhOpenQueryW(nullptr, NULL, &_query); if (status != ERROR_SUCCESS) { return {ErrorCodes::WindowsPdhError, formatFunctionCallError("PdhOpenQueryW", status)}; } return Status::OK(); }
CCPUInfo::CCPUInfo(void) { #ifdef TARGET_POSIX m_fProcStat = m_fProcTemperature = m_fCPUFreq = NULL; m_cpuInfoForFreq = false; #elif defined(TARGET_WINDOWS) m_cpuQueryFreq = NULL; m_cpuQueryLoad = NULL; #endif m_lastUsedPercentage = 0; m_cpuFeatures = 0; #if defined(TARGET_DARWIN) size_t len = 4; std::string cpuVendor; // The number of cores. if (sysctlbyname("hw.activecpu", &m_cpuCount, &len, NULL, 0) == -1) m_cpuCount = 1; // The model. #if defined(__ppc__) || defined (TARGET_DARWIN_IOS) const NXArchInfo *info = NXGetLocalArchInfo(); if (info != NULL) m_cpuModel = info->description; #else // NXGetLocalArchInfo is ugly for intel so keep using this method char buffer[512]; len = 512; if (sysctlbyname("machdep.cpu.brand_string", &buffer, &len, NULL, 0) == 0) m_cpuModel = buffer; // The CPU vendor len = 512; if (sysctlbyname("machdep.cpu.vendor", &buffer, &len, NULL, 0) == 0) cpuVendor = buffer; #endif // Go through each core. for (int i=0; i<m_cpuCount; i++) { CoreInfo core; core.m_id = i; core.m_strModel = m_cpuModel; core.m_strVendor = cpuVendor; m_cores[core.m_id] = core; } #elif defined(TARGET_WINDOWS) HKEY hKeyCpuRoot; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", 0, KEY_READ, &hKeyCpuRoot) == ERROR_SUCCESS) { DWORD num = 0; std::vector<CoreInfo> cpuCores; wchar_t subKeyName[200]; // more than enough DWORD subKeyNameLen = sizeof(subKeyName) / sizeof(wchar_t); while (RegEnumKeyExW(hKeyCpuRoot, num++, subKeyName, &subKeyNameLen, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { HKEY hCpuKey; if (RegOpenKeyExW(hKeyCpuRoot, subKeyName, 0, KEY_QUERY_VALUE, &hCpuKey) == ERROR_SUCCESS) { CoreInfo cpuCore; if (swscanf_s(subKeyName, L"%i", &cpuCore.m_id) != 1) cpuCore.m_id = num - 1; wchar_t buf[300]; // more than enough DWORD bufSize = sizeof(buf); DWORD valType; if (RegQueryValueExW(hCpuKey, L"ProcessorNameString", NULL, &valType, (LPBYTE)buf, &bufSize) == ERROR_SUCCESS && valType == REG_SZ) { g_charsetConverter.wToUTF8(std::wstring(buf, bufSize / sizeof(wchar_t)), cpuCore.m_strModel); cpuCore.m_strModel = cpuCore.m_strModel.substr(0, cpuCore.m_strModel.find(char(0))); // remove extra null terminations StringUtils::RemoveDuplicatedSpacesAndTabs(cpuCore.m_strModel); StringUtils::Trim(cpuCore.m_strModel); } bufSize = sizeof(buf); if (RegQueryValueExW(hCpuKey, L"VendorIdentifier", NULL, &valType, (LPBYTE)buf, &bufSize) == ERROR_SUCCESS && valType == REG_SZ) { g_charsetConverter.wToUTF8(std::wstring(buf, bufSize / sizeof(wchar_t)), cpuCore.m_strVendor); cpuCore.m_strVendor = cpuCore.m_strVendor.substr(0, cpuCore.m_strVendor.find(char(0))); // remove extra null terminations } DWORD mhzVal; bufSize = sizeof(mhzVal); if (RegQueryValueExW(hCpuKey, L"~MHz", NULL, &valType, (LPBYTE)&mhzVal, &bufSize) == ERROR_SUCCESS && valType == REG_DWORD) cpuCore.m_fSpeed = double(mhzVal); RegCloseKey(hCpuKey); if (cpuCore.m_strModel.empty()) cpuCore.m_strModel = "Unknown"; cpuCores.push_back(cpuCore); } subKeyNameLen = sizeof(subKeyName) / sizeof(wchar_t); // restore length value } RegCloseKey(hKeyCpuRoot); std::sort(cpuCores.begin(), cpuCores.end()); // sort cores by id for (size_t i = 0; i < cpuCores.size(); i++) m_cores[i] = cpuCores[i]; // add in sorted order } if (!m_cores.empty()) m_cpuModel = m_cores.begin()->second.m_strModel; else m_cpuModel = "Unknown"; SYSTEM_INFO siSysInfo; GetNativeSystemInfo(&siSysInfo); m_cpuCount = siSysInfo.dwNumberOfProcessors; if (PdhOpenQueryW(NULL, 0, &m_cpuQueryFreq) == ERROR_SUCCESS) { if (PdhAddEnglishCounterW(m_cpuQueryFreq, L"\\Processor Information(0,0)\\Processor Frequency", 0, &m_cpuFreqCounter) != ERROR_SUCCESS) m_cpuFreqCounter = NULL; } else m_cpuQueryFreq = NULL; if (PdhOpenQueryW(NULL, 0, &m_cpuQueryLoad) == ERROR_SUCCESS) { for (size_t i = 0; i < m_cores.size(); i++) { if (PdhAddEnglishCounterW(m_cpuQueryLoad, StringUtils::Format(L"\\Processor(%d)\\%% Idle Time", int(i)).c_str(), 0, &m_cores[i].m_coreCounter) != ERROR_SUCCESS) m_cores[i].m_coreCounter = NULL; } } else m_cpuQueryLoad = NULL; #elif defined(TARGET_FREEBSD) size_t len; int i; char cpumodel[512]; len = sizeof(m_cpuCount); if (sysctlbyname("hw.ncpu", &m_cpuCount, &len, NULL, 0) != 0) m_cpuCount = 1; len = sizeof(cpumodel); if (sysctlbyname("hw.model", &cpumodel, &len, NULL, 0) != 0) (void)strncpy(cpumodel, "Unknown", 8); m_cpuModel = cpumodel; for (i = 0; i < m_cpuCount; i++) { CoreInfo core; core.m_id = i; core.m_strModel = m_cpuModel; m_cores[core.m_id] = core; } #else m_fProcStat = fopen("/proc/stat", "r"); m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THM0/temperature", "r"); if (m_fProcTemperature == NULL) m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THRM/temperature", "r"); if (m_fProcTemperature == NULL) m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THR0/temperature", "r"); if (m_fProcTemperature == NULL) m_fProcTemperature = fopen("/proc/acpi/thermal_zone/TZ0/temperature", "r"); // read from the new location of the temperature data on new kernels, 2.6.39, 3.0 etc if (m_fProcTemperature == NULL) m_fProcTemperature = fopen("/sys/class/hwmon/hwmon0/temp1_input", "r"); if (m_fProcTemperature == NULL) m_fProcTemperature = fopen("/sys/class/thermal/thermal_zone0/temp", "r"); // On Raspberry PIs m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r"); if (!m_fCPUFreq) { m_cpuInfoForFreq = true; m_fCPUFreq = fopen("/proc/cpuinfo", "r"); } else m_cpuInfoForFreq = false; FILE* fCPUInfo = fopen("/proc/cpuinfo", "r"); m_cpuCount = 0; if (fCPUInfo) { char buffer[512]; int nCurrId = 0; while (fgets(buffer, sizeof(buffer), fCPUInfo)) { if (strncmp(buffer, "processor", strlen("processor"))==0) { char *needle = strstr(buffer, ":"); if (needle) { CoreInfo core; core.m_id = atoi(needle+2); nCurrId = core.m_id; m_cores[core.m_id] = core; } m_cpuCount++; } else if (strncmp(buffer, "vendor_id", strlen("vendor_id"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cores[nCurrId].m_strVendor = needle; StringUtils::Trim(m_cores[nCurrId].m_strVendor); } } else if (strncmp(buffer, "Processor", strlen("Processor"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuModel = needle; m_cores[nCurrId].m_strModel = m_cpuModel; StringUtils::Trim(m_cores[nCurrId].m_strModel); } } else if (strncmp(buffer, "BogoMIPS", strlen("BogoMIPS"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuBogoMips = needle; m_cores[nCurrId].m_strBogoMips = m_cpuBogoMips; StringUtils::Trim(m_cores[nCurrId].m_strBogoMips); } } else if (strncmp(buffer, "Hardware", strlen("Hardware"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuHardware = needle; m_cores[nCurrId].m_strHardware = m_cpuHardware; StringUtils::Trim(m_cores[nCurrId].m_strHardware); } } else if (strncmp(buffer, "Revision", strlen("Revision"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuRevision = needle; m_cores[nCurrId].m_strRevision = m_cpuRevision; StringUtils::Trim(m_cores[nCurrId].m_strRevision); } } else if (strncmp(buffer, "Serial", strlen("Serial"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuSerial = needle; m_cores[nCurrId].m_strSerial = m_cpuSerial; StringUtils::Trim(m_cores[nCurrId].m_strSerial); } } else if (strncmp(buffer, "model name", strlen("model name"))==0) { char *needle = strstr(buffer, ":"); if (needle && strlen(needle)>3) { needle+=2; m_cpuModel = needle; m_cores[nCurrId].m_strModel = m_cpuModel; StringUtils::Trim(m_cores[nCurrId].m_strModel); } } else if (strncmp(buffer, "flags", 5) == 0) { char* needle = strchr(buffer, ':'); if (needle) { char* tok = NULL, * save; needle++; tok = strtok_r(needle, " ", &save); while (tok) { if (0 == strcmp(tok, "mmx")) m_cpuFeatures |= CPU_FEATURE_MMX; else if (0 == strcmp(tok, "mmxext")) m_cpuFeatures |= CPU_FEATURE_MMX2; else if (0 == strcmp(tok, "sse")) m_cpuFeatures |= CPU_FEATURE_SSE; else if (0 == strcmp(tok, "sse2")) m_cpuFeatures |= CPU_FEATURE_SSE2; else if (0 == strcmp(tok, "sse3")) m_cpuFeatures |= CPU_FEATURE_SSE3; else if (0 == strcmp(tok, "ssse3")) m_cpuFeatures |= CPU_FEATURE_SSSE3; else if (0 == strcmp(tok, "sse4_1")) m_cpuFeatures |= CPU_FEATURE_SSE4; else if (0 == strcmp(tok, "sse4_2")) m_cpuFeatures |= CPU_FEATURE_SSE42; else if (0 == strcmp(tok, "3dnow")) m_cpuFeatures |= CPU_FEATURE_3DNOW; else if (0 == strcmp(tok, "3dnowext")) m_cpuFeatures |= CPU_FEATURE_3DNOWEXT; tok = strtok_r(NULL, " ", &save); } } } } fclose(fCPUInfo); } else { m_cpuCount = 1; m_cpuModel = "Unknown"; } #endif StringUtils::Replace(m_cpuModel, '\r', ' '); StringUtils::Replace(m_cpuModel, '\n', ' '); StringUtils::RemoveDuplicatedSpacesAndTabs(m_cpuModel); StringUtils::Trim(m_cpuModel); /* Set some default for empty string variables */ if (m_cpuBogoMips.empty()) m_cpuBogoMips = "N/A"; if (m_cpuHardware.empty()) m_cpuHardware = "N/A"; if (m_cpuRevision.empty()) m_cpuRevision = "N/A"; if (m_cpuSerial.empty()) m_cpuSerial = "N/A"; readProcStat(m_userTicks, m_niceTicks, m_systemTicks, m_idleTicks, m_ioTicks); m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS); ReadCPUFeatures(); // Set MMX2 when SSE is present as SSE is a superset of MMX2 and Intel doesn't set the MMX2 cap if (m_cpuFeatures & CPU_FEATURE_SSE) m_cpuFeatures |= CPU_FEATURE_MMX2; if (HasNeon()) m_cpuFeatures |= CPU_FEATURE_NEON; }