]> git.ipfire.org Git - pakfire.git/commitdiff
os: Add function to gather cpu stats
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 30 Oct 2023 11:00:11 +0000 (11:00 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 30 Oct 2023 11:00:11 +0000 (11:00 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/os.h
src/libpakfire/os.c
tests/libpakfire/os.c

index dd600e633850463f490732331da2d96fedc6f40b..70e608bee639913c69dadc7989e74b804f41ea41 100644 (file)
@@ -37,6 +37,23 @@ struct pakfire_cpuinfo {
 
 int pakfire_cpuinfo(struct pakfire_cpuinfo* cpuinfo);
 
+// CPU stat
+
+struct pakfire_cpustat {
+       double user;
+       double nice;
+       double system;
+       double idle;
+       double iowait;
+       double irq;
+       double softirq;
+       double steal;
+       double guest;
+       double guest_nice;
+};
+
+int pakfire_cpustat(struct pakfire_cpustat* cpustat);
+
 // Meminfo
 
 struct pakfire_meminfo {
index 63a225e66ef24b44aa1bc11d4531ce3f03fc1ba8..bfb03a7dfe00d716d27145bbdb57d7d952ac61b5 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <pakfire/os.h>
 #include <pakfire/string.h>
@@ -141,6 +142,55 @@ int pakfire_cpuinfo(struct pakfire_cpuinfo* cpuinfo) {
        return pakfire_parse_file("/proc/cpuinfo", pakfire_parse_cpuinfo, cpuinfo);
 }
 
+// CPU Stats
+
+static int pakfire_parse_cpustat(char* line, size_t length, void* data) {
+       struct pakfire_cpustat* cpustat = data;
+       struct cpustat {
+               unsigned long int user;
+               unsigned long int nice;
+               unsigned long int system;
+               unsigned long int idle;
+               unsigned long int iowait;
+               unsigned long int irq;
+               unsigned long int softirq;
+               unsigned long int steal;
+               unsigned long int guest;
+               unsigned long int guest_nice;
+       } stat;
+       int r;
+
+       // Only care about the line of interest
+       if (pakfire_string_startswith(line, "cpu ")) {
+               r = sscanf(line, "cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+                       &stat.user, &stat.nice, &stat.system, &stat.idle, &stat.iowait,
+                       &stat.irq, &stat.softirq, &stat.steal, &stat.guest, &stat.guest_nice);
+               if (r < 10)
+                       return -EINVAL;
+
+               // Fetch how many ticks a second
+               long int ticks = sysconf(_SC_CLK_TCK);
+
+               // Convert to relative terms
+               cpustat->user       = stat.user       / ticks;
+               cpustat->nice       = stat.nice       / ticks;
+               cpustat->system     = stat.system     / ticks;
+               cpustat->idle       = stat.idle       / ticks;
+               cpustat->iowait     = stat.iowait     / ticks;
+               cpustat->irq        = stat.irq        / ticks;
+               cpustat->softirq    = stat.softirq    / ticks;
+               cpustat->steal      = stat.steal      / ticks;
+               cpustat->guest      = stat.guest      / ticks;
+               cpustat->guest_nice = stat.guest_nice / ticks;
+       }
+
+       return 0;
+}
+
+int pakfire_cpustat(struct pakfire_cpustat* cpustat) {
+       return pakfire_parse_file("/proc/stat", pakfire_parse_cpustat, cpustat);
+}
+
 // Meminfo
 
 static int pakfire_parse_meminfo_value(uint64_t* mem, const char* s) {
index e631bad1e0920ae5cb7f37d7f9d991810e4544ad..9cc6a27da6ffaf9e2016ed3c4564e9a51c262640 100644 (file)
@@ -38,6 +38,29 @@ FAIL:
        return EXIT_FAILURE;
 }
 
+// This test parses /proc/stat
+static int test_cpustat(const struct test* t) {
+       struct pakfire_cpustat cpustat = {};
+
+       ASSERT_SUCCESS(pakfire_cpustat(&cpustat));
+
+       ASSERT(cpustat.user       >= 0);
+       ASSERT(cpustat.nice       >= 0);
+       ASSERT(cpustat.system     >= 0);
+       ASSERT(cpustat.idle       >= 0);
+       ASSERT(cpustat.iowait     >= 0);
+       ASSERT(cpustat.irq        >= 0);
+       ASSERT(cpustat.softirq    >= 0);
+       ASSERT(cpustat.steal      >= 0);
+       ASSERT(cpustat.guest      >= 0);
+       ASSERT(cpustat.guest_nice >= 0);
+
+       return EXIT_SUCCESS;
+
+FAIL:
+       return EXIT_FAILURE;
+}
+
 // This test parses /proc/meminfo
 static int test_meminfo(const struct test* t) {
        struct pakfire_meminfo meminfo = {};
@@ -65,6 +88,7 @@ FAIL:
 
 int main(int argc, const char* argv[]) {
        testsuite_add_test(test_cpuinfo);
+       testsuite_add_test(test_cpustat);
        testsuite_add_test(test_meminfo);
 
        return testsuite_run(argc, argv);