From efa45f5f470de4991398655b61cf6abe7843d755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 13 Aug 2026 18:41:01 +0200 Subject: [PATCH] basic/procfs-util: add procfs_cpu_get_ticks() --- src/basic/procfs-util.c | 33 +++++++++++++++++++++++++++++++++ src/basic/procfs-util.h | 13 +++++++++++++ src/test/test-procfs-util.c | 8 ++++++++ 3 files changed, 54 insertions(+) diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c index 9ddffe2d37..f11c849baf 100644 --- a/src/basic/procfs-util.c +++ b/src/basic/procfs-util.c @@ -171,6 +171,39 @@ int procfs_cpu_get_usage(nsec_t *ret) { return 0; } +int procfs_cpu_get_ticks(ProcfsCpuTicks *ret) { + _cleanup_free_ char *first_line = NULL; + int r; + + assert(ret); + + r = read_one_line_file("/proc/stat", &first_line); + if (r < 0) + return r; + + const char *p = first_word(first_line, "cpu"); + if (!p) + return -EINVAL; + + /* All eight fields exist on any kernel we support: iowait was added in 2.5.41, steal in 2.6.11. + * "guest" and "guest_nice" are not returned, the kernel already includes them in "user" and + * "nice". */ + ProcfsCpuTicks t; + if (sscanf(p, "%"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64, + &t.user, + &t.nice, + &t.system, + &t.idle, + &t.iowait, + &t.irq, + &t.softirq, + &t.steal) < 8) + return -EINVAL; + + *ret = t; + return 0; +} + int convert_meminfo_value_to_uint64_bytes(const char *s, uint64_t *ret) { _cleanup_free_ char *w = NULL; uint64_t v; diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h index cf091d1e07..15a07871d1 100644 --- a/src/basic/procfs-util.h +++ b/src/basic/procfs-util.h @@ -11,6 +11,19 @@ int procfs_tasks_get_current(uint64_t *ret); int procfs_cpu_get_usage(nsec_t *ret); +typedef struct ProcfsCpuTicks { + uint64_t user; + uint64_t nice; + uint64_t system; + uint64_t idle; + uint64_t iowait; + uint64_t irq; + uint64_t softirq; + uint64_t steal; +} ProcfsCpuTicks; + +int procfs_cpu_get_ticks(ProcfsCpuTicks *ret); + int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used); static inline int procfs_memory_get_used(uint64_t *ret) { return procfs_memory_get(NULL, ret); diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c index 9a368f9f18..14def54ee0 100644 --- a/src/test/test-procfs-util.c +++ b/src/test/test-procfs-util.c @@ -18,6 +18,14 @@ int main(int argc, char *argv[]) { ASSERT_OK(procfs_cpu_get_usage(&nsec)); log_info("Current system CPU time: %s", FORMAT_TIMESPAN(nsec/NSEC_PER_USEC, 1)); + ProcfsCpuTicks ticks; + ASSERT_OK(procfs_cpu_get_ticks(&ticks)); + log_info("Current CPU ticks: user=%" PRIu64 " nice=%" PRIu64 " system=%" PRIu64 " idle=%" PRIu64 + " iowait=%" PRIu64 " irq=%" PRIu64 " softirq=%" PRIu64 " steal=%" PRIu64, + ticks.user, ticks.nice, ticks.system, ticks.idle, + ticks.iowait, ticks.irq, ticks.softirq, ticks.steal); + ASSERT_GT(ticks.idle, 0U); + ASSERT_OK(procfs_memory_get_used(&v)); log_info("Current memory usage: %s", FORMAT_BYTES(v));