int CCPUInfo::getUsedPercentage() { if (!m_nextUsedReadTime.IsTimePast()) return m_lastUsedPercentage; unsigned long long userTicks; unsigned long long niceTicks; unsigned long long systemTicks; unsigned long long idleTicks; unsigned long long ioTicks; if (!readProcStat(userTicks, niceTicks, systemTicks, idleTicks, ioTicks)) return m_lastUsedPercentage; userTicks -= m_userTicks; niceTicks -= m_niceTicks; systemTicks -= m_systemTicks; idleTicks -= m_idleTicks; ioTicks -= m_ioTicks; if(userTicks + niceTicks + systemTicks + idleTicks + ioTicks == 0) return m_lastUsedPercentage; int result = (int) (double(userTicks + niceTicks + systemTicks) * 100.0 / double(userTicks + niceTicks + systemTicks + idleTicks + ioTicks) + 0.5); m_userTicks += userTicks; m_niceTicks += niceTicks; m_systemTicks += systemTicks; m_idleTicks += idleTicks; m_ioTicks += ioTicks; m_lastUsedPercentage = result; m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS); return result; }
bool readProcSysDependencies(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) { bool result = false; DIR *proc = opendir("/proc"); if (proc == NULL) { logg.logMessage("opendir failed"); return result; } struct dirent *dirent; while ((dirent = readdir(proc)) != NULL) { char *endptr; const int pid = strtol(dirent->d_name, &endptr, 10); if (*endptr != '\0') { // Ignore proc items that are not integers like ., cpuinfo, etc... continue; } if (!printb->printf("/proc/%i/stat", pid)) { logg.logMessage("DynBuf::printf failed"); goto fail; } ProcStat ps; if (!readProcStat(&ps, printb->getBuf(), b1)) { logg.logMessage("readProcStat failed"); goto fail; } if (ps.numThreads <= 1) { const char *const image = readProcExe(printb, pid, -1, b1); if (image == NULL) { logg.logMessage("readImage failed"); goto fail; } buffer->marshalComm(currTime, pid, pid, image, ps.comm); } else { if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) { logg.logMessage("readProcTask failed"); goto fail; } } } if (gSessionData.mFtraceRaw) { if (!gSessionData.mFtraceDriver.readTracepointFormats(currTime, buffer, printb, b1)) { logg.logMessage("FtraceDriver::readTracepointFormats failed"); goto fail; } } result = true; fail: closedir(proc); return result; }
static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) { bool result = false; if (!b1->printf("/proc/%i/task", pid)) { logg.logMessage("DynBuf::printf failed"); return result; } DIR *task = opendir(b1->getBuf()); if (task == NULL) { logg.logMessage("opendir failed"); // This is not a fatal error - the thread just doesn't exist any more return true; } struct dirent *dirent; while ((dirent = readdir(task)) != NULL) { char *endptr; const int tid = strtol(dirent->d_name, &endptr, 10); if (*endptr != '\0') { // Ignore task items that are not integers like ., etc... continue; } if (!printb->printf("/proc/%i/task/%i/stat", pid, tid)) { logg.logMessage("DynBuf::printf failed"); goto fail; } ProcStat ps; if (!readProcStat(&ps, printb->getBuf(), b1)) { logg.logMessage("readProcStat failed"); goto fail; } const char *const image = readProcExe(printb, pid, tid, b2); if (image == NULL) { logg.logMessage("readImage failed"); goto fail; } buffer->marshalComm(currTime, pid, tid, image, ps.comm); } result = true; fail: closedir(task); return result; }
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; }