]> git.ipfire.org Git - pakfire.git/commitdiff
cgroups: Add function to get cpu stats
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Mar 2021 22:08:20 +0000 (22:08 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Mar 2021 22:08:20 +0000 (22:08 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/cgroup.c
src/libpakfire/include/pakfire/cgroup.h
tests/libpakfire/cgroup.c

index 8e2c713e181bae21162cedad52cd332a715d25e3..6a16e2a9ed3d086495c2b23f286a57d11e158d84 100644 (file)
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
+#include <time.h>
 
 #include <pakfire/cgroup.h>
 #include <pakfire/logging.h>
@@ -408,3 +409,47 @@ int pakfire_cgroup_killall(Pakfire pakfire, const char* group) {
 
        return 1;
 }
+
+int pakfire_cgroup_cpustat(Pakfire pakfire, const char* group,
+               struct pakfire_cgroup_cpustat* st) {
+       FILE* f = pakfire_cgroup_fopen(pakfire, group, "cpu.stat", "r");
+       if (!f)
+               return 1;
+
+       const struct keyword {
+               const char* keyword;
+               struct timeval* value;
+       } keywords[] = {
+               { "usage_usec", &st->usage },
+               { "user_usec", &st->user },
+               { "system_usec", &st->system },
+               { NULL, NULL },
+       };
+
+       char* line = NULL;
+       size_t l = 0;
+
+       while (1) {
+               ssize_t bytes_read = getline(&line, &l, f);
+               if (bytes_read < 0)
+                       break;
+
+               printf("%s", line);
+
+               for (const struct keyword* keyword = keywords; keyword->keyword; keyword++) {
+                       if (pakfire_string_startswith(line, keyword->keyword)) {
+                               const char* p = line + strlen(keyword->keyword) + 1;
+
+                               unsigned long long v = strtoull(p, NULL, 10);
+
+                               // Set value
+                               keyword->value->tv_sec  = v / 1000000;
+                               keyword->value->tv_usec = v % 1000000;
+                       }
+               }
+       }
+       
+       fclose(f);
+
+       return 0;
+}
index f474faad8a069bfa9d46b454c3254b1a3f2cd915..cdbeb047c0e10334a024ec1b2a82e985ea035c05 100644 (file)
@@ -24,6 +24,7 @@
 #ifdef PAKFIRE_PRIVATE
 
 #include <sys/types.h>
+#include <time.h>
 
 #include <pakfire/types.h>
 
@@ -37,6 +38,15 @@ ssize_t pakfire_cgroup_num_processes(Pakfire pakfire, const char* group);
 
 int pakfire_cgroup_killall(Pakfire pakfire, const char* group);
 
+struct pakfire_cgroup_cpustat {
+       struct timeval usage;
+       struct timeval user;
+       struct timeval system;
+};
+
+int pakfire_cgroup_cpustat(Pakfire pakfire, const char* group,
+               struct pakfire_cgroup_cpustat* st);
+
 #endif
 
 #endif /* PAKFIRE_CGROUP_H */
index 8bd32c1250ca1486e7a462c37ef4044c57a381ab..283cc0c6875308164791974b3e6f96bf17718a48 100644 (file)
@@ -132,10 +132,42 @@ static int test_killall(const struct test* t) {
        );
 }
 
+static int test_cpustat(const struct test* t) {
+       struct pakfire_cgroup_cpustat st;
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_create(t->pakfire, "pakfire/test")
+       );
+
+       // Launch a background we can kill :)
+       pid_t pid = fork_child_process();
+
+       // Attach child to cgroup
+       ASSERT_SUCCESS(
+               pakfire_cgroup_attach(t->pakfire, "pakfire/test", pid)
+       );
+
+       // Kill everything
+       ASSERT_SUCCESS(
+               pakfire_cgroup_killall(t->pakfire, "pakfire/test")
+       );
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_cpustat(t->pakfire, "pakfire/test", &st)
+       );
+
+       ASSERT(st.usage.tv_sec > 0 || st.usage.tv_usec > 0);
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_destroy(t->pakfire, "pakfire/test")
+       );
+}
+
 int main(int argc, char** argv) {
        testsuite_add_test(test_create_and_destroy);
        testsuite_add_test(test_attach);
        testsuite_add_test(test_killall);
+       testsuite_add_test(test_cpustat);
 
        return testsuite_run();
 }