From 4e567d0483481191ac019b3531b10f6afcc9688a Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sun, 11 Aug 2019 13:10:37 +0000 Subject: [PATCH] cpu: port parseCpuinfo to BSDs --- include/factory.hpp | 2 + include/modules/cpu.hpp | 1 - meson.build | 7 +- src/factory.cpp | 2 + src/modules/cpu/bsd.cpp | 97 +++++++++++++++++++++++++ src/modules/{cpu.cpp => cpu/common.cpp} | 28 ------- src/modules/cpu/linux.cpp | 29 ++++++++ 7 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 src/modules/cpu/bsd.cpp rename src/modules/{cpu.cpp => cpu/common.cpp} (68%) create mode 100644 src/modules/cpu/linux.cpp diff --git a/include/factory.hpp b/include/factory.hpp index dfd0cc7f..e584b251 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -10,7 +10,9 @@ #if defined(__linux__) && !defined(NO_FILESYSTEM) #include "modules/battery.hpp" #endif +#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) #include "modules/cpu.hpp" +#endif #include "modules/idle_inhibitor.hpp" #if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD) #include "modules/memory.hpp" diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp index 1b490faf..7a703364 100644 --- a/include/modules/cpu.hpp +++ b/include/modules/cpu.hpp @@ -20,7 +20,6 @@ class Cpu : public ALabel { auto update() -> void; private: - static inline const std::string data_dir_ = "/proc/stat"; uint16_t getCpuLoad(); std::tuple getCpuUsage(); std::vector> parseCpuinfo(); diff --git a/meson.build b/meson.build index 5dd3b1b9..5a8570c2 100644 --- a/meson.build +++ b/meson.build @@ -120,7 +120,6 @@ src_files = files( 'src/modules/bluetooth.cpp', 'src/modules/clock.cpp', 'src/modules/custom.cpp', - 'src/modules/cpu.cpp', 'src/modules/disk.cpp', 'src/modules/idle_inhibitor.cpp', 'src/modules/temperature.cpp', @@ -131,15 +130,21 @@ src_files = files( ) if is_linux + add_project_arguments('-DHAVE_CPU_LINUX', language: 'cpp') add_project_arguments('-DHAVE_MEMORY_LINUX', language: 'cpp') src_files += files( 'src/modules/battery.cpp', + 'src/modules/cpu/common.cpp', + 'src/modules/cpu/linux.cpp', 'src/modules/memory/common.cpp', 'src/modules/memory/linux.cpp', ) elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd + add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp') add_project_arguments('-DHAVE_MEMORY_BSD', language: 'cpp') src_files += files( + 'src/modules/cpu/bsd.cpp', + 'src/modules/cpu/common.cpp', 'src/modules/memory/bsd.cpp', 'src/modules/memory/common.cpp', ) diff --git a/src/factory.cpp b/src/factory.cpp index 4b3f3377..88a1322b 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -31,9 +31,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { return new waybar::modules::Memory(id, config_[name]); } #endif +#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) if (ref == "cpu") { return new waybar::modules::Cpu(id, config_[name]); } +#endif if (ref == "clock") { return new waybar::modules::Clock(id, config_[name]); } diff --git a/src/modules/cpu/bsd.cpp b/src/modules/cpu/bsd.cpp new file mode 100644 index 00000000..73ab1e8a --- /dev/null +++ b/src/modules/cpu/bsd.cpp @@ -0,0 +1,97 @@ +#include "modules/cpu.hpp" + +#include +#include +#include // malloc +#include // sysconf + +#if defined(__NetBSD__) || defined(__OpenBSD__) +# include +#else +# include +#endif + +#if defined(__NetBSD__) +typedef uint64_t cp_time_t; +#else +typedef long cp_time_t; +#endif +#if defined(__NetBSD__) || defined(__OpenBSD__) +typedef uint64_t pcp_time_t; +#else +typedef long pcp_time_t; +#endif + +std::vector> waybar::modules::Cpu::parseCpuinfo() { + cp_time_t sum_cp_time[CPUSTATES]; + size_t sum_sz = sizeof(sum_cp_time); + int ncpu = sysconf(_SC_NPROCESSORS_CONF); + size_t sz = CPUSTATES * (ncpu + 1) * sizeof(pcp_time_t); + pcp_time_t *cp_time = static_cast(malloc(sz)), *pcp_time = cp_time; +#if defined(__NetBSD__) + int mib[] = { + CTL_KERN, + KERN_CP_TIME, + }; + if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_time failed"); + } + for (int state = 0; state < CPUSTATES; state++) { + cp_time[state] = sum_cp_time[state]; + } + pcp_time += CPUSTATES; + if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_time failed"); + } +#elif defined(__OpenBSD__) + { + int mib[] = { + CTL_KERN, + KERN_CPTIME, + }; + if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_time failed"); + } + } + for (int state = 0; state < CPUSTATES; state++) { + cp_time[state] = sum_cp_time[state]; + } + pcp_time = cp_time; + sz /= ncpu + 1; + { + int mib[] = { + CTL_KERN, + KERN_CPTIME2, + 0, + }; + for (int cpu = 0; cpu < ncpu; cpu++) { + mib[2] = cpu; + pcp_time += CPUSTATES; + if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_time2 failed"); + } + } + } +#else + if (sysctlbyname("kern.cp_time", sum_cp_time, &sum_sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_time failed"); + } + for (int state = 0; state < CPUSTATES; state++) { + cp_time[state] = sum_cp_time[state]; + } + pcp_time += CPUSTATES; + if (sysctlbyname("kern.cp_times", pcp_time, &sz, NULL, 0)) { + throw std::runtime_error("sysctl kern.cp_times failed"); + } +#endif + std::vector> cpuinfo; + for (int cpu = 0; cpu < ncpu + 1; cpu++) { + pcp_time_t total = 0, *single_cp_time = &cp_time[cpu * CPUSTATES]; + for (int state = 0; state < CPUSTATES; state++) { + total += single_cp_time[state]; + } + cpuinfo.emplace_back(single_cp_time[CP_IDLE], total); + } + free(cp_time); + return cpuinfo; +} diff --git a/src/modules/cpu.cpp b/src/modules/cpu/common.cpp similarity index 68% rename from src/modules/cpu.cpp rename to src/modules/cpu/common.cpp index 79b84d52..f2204cde 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu/common.cpp @@ -1,5 +1,4 @@ #include "modules/cpu.hpp" -#include waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config) : ALabel(config, "cpu", id, "{usage}%", 10) { @@ -54,30 +53,3 @@ std::tuple waybar::modules::Cpu::getCpuUsage() { prev_times_ = curr_times; return {usage, tooltip}; } - -std::vector> waybar::modules::Cpu::parseCpuinfo() { - std::ifstream info(data_dir_); - if (!info.is_open()) { - throw std::runtime_error("Can't open " + data_dir_); - } - std::vector> cpuinfo; - std::string line; - while (getline(info, line)) { - if (line.substr(0, 3).compare("cpu") != 0) { - break; - } - std::stringstream sline(line.substr(5)); - std::vector times; - for (size_t time = 0; sline >> time; times.push_back(time)) - ; - - size_t idle_time = 0; - size_t total_time = 0; - if (times.size() >= 4) { - idle_time = times[3]; - total_time = std::accumulate(times.begin(), times.end(), 0); - } - cpuinfo.emplace_back(idle_time, total_time); - } - return cpuinfo; -} diff --git a/src/modules/cpu/linux.cpp b/src/modules/cpu/linux.cpp new file mode 100644 index 00000000..9f1734fb --- /dev/null +++ b/src/modules/cpu/linux.cpp @@ -0,0 +1,29 @@ +#include "modules/cpu.hpp" + +std::vector> waybar::modules::Cpu::parseCpuinfo() { + const std::string data_dir_ = "/proc/stat"; + std::ifstream info(data_dir_); + if (!info.is_open()) { + throw std::runtime_error("Can't open " + data_dir_); + } + std::vector> cpuinfo; + std::string line; + while (getline(info, line)) { + if (line.substr(0, 3).compare("cpu") != 0) { + break; + } + std::stringstream sline(line.substr(5)); + std::vector times; + for (size_t time = 0; sline >> time; times.push_back(time)) + ; + + size_t idle_time = 0; + size_t total_time = 0; + if (times.size() >= 4) { + idle_time = times[3]; + total_time = std::accumulate(times.begin(), times.end(), 0); + } + cpuinfo.emplace_back(idle_time, total_time); + } + return cpuinfo; +}