| 3 | #include "modules/cpu_usage.hpp" |
| 4 | |
| 5 | std::vector<std::tuple<size_t, size_t>> waybar::modules::CpuUsage::parseCpuinfo() { |
| 6 | // Get the "existing CPU count" from /sys/devices/system/cpu/present |
| 7 | // Probably this is what the user wants the offline CPUs accounted from |
| 8 | // For further details see: |
| 9 | // https://www.kernel.org/doc/html/latest/core-api/cpu_hotplug.html |
| 10 | const std::string sys_cpu_present_path = "/sys/devices/system/cpu/present"; |
| 11 | size_t cpu_present_last = 0; |
| 12 | std::ifstream cpu_present_file(sys_cpu_present_path); |
| 13 | std::string cpu_present_text; |
| 14 | if (cpu_present_file.is_open()) { |
| 15 | getline(cpu_present_file, cpu_present_text); |
| 16 | // This is a comma-separated list of ranges, eg. 0,2-4,7 |
| 17 | size_t last_separator = cpu_present_text.find_last_of("-,"); |
| 18 | if (last_separator < cpu_present_text.size()) { |
| 19 | std::stringstream(cpu_present_text.substr(last_separator + 1)) >> cpu_present_last; |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | const std::string data_dir_ = "/proc/stat"; |
| 24 | std::ifstream info(data_dir_); |
| 25 | if (!info.is_open()) { |
| 26 | throw std::runtime_error("Can't open " + data_dir_); |
| 27 | } |
| 28 | std::vector<std::tuple<size_t, size_t>> cpuinfo; |
| 29 | std::string line; |
| 30 | size_t current_cpu_number = -1; // First line is total, second line is cpu 0 |
| 31 | while (getline(info, line)) { |
| 32 | if (line.substr(0, 3).compare("cpu") != 0) { |
| 33 | break; |
| 34 | } |
| 35 | size_t line_cpu_number; |
| 36 | if (current_cpu_number >= 0) { |
| 37 | std::stringstream(line.substr(3)) >> line_cpu_number; |
| 38 | while (line_cpu_number > current_cpu_number) { |
| 39 | // Fill in 0 for offline CPUs missing inside the lines of /proc/stat |
| 40 | cpuinfo.emplace_back(0, 0); |
| 41 | current_cpu_number++; |
| 42 | } |
| 43 | } |
| 44 | std::stringstream sline(line.substr(5)); |
| 45 | std::vector<size_t> times; |
| 46 | for (size_t time = 0; sline >> time; times.push_back(time)); |
| 47 | |
| 48 | size_t idle_time = 0; |
| 49 | size_t total_time = 0; |
| 50 | if (times.size() >= 5) { |
| 51 | // idle + iowait |
| 52 | idle_time = times[3] + times[4]; |
| 53 | total_time = std::accumulate(times.begin(), times.end(), 0); |
| 54 | } |
| 55 | cpuinfo.emplace_back(idle_time, total_time); |
| 56 | current_cpu_number++; |
| 57 | } |
| 58 | |
| 59 | while (cpu_present_last >= current_cpu_number) { |
| 60 | // Fill in 0 for offline CPUs missing after the lines of /proc/stat |
| 61 | cpuinfo.emplace_back(0, 0); |
| 62 | current_cpu_number++; |