From: Michael Tremer Date: Mon, 29 Mar 2021 22:08:20 +0000 (+0000) Subject: cgroups: Add function to get cpu stats X-Git-Tag: 0.9.28~1285^2~453 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d52562246380c2eb575be7f526d4b3a8edb9f983;p=pakfire.git cgroups: Add function to get cpu stats Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 8e2c713e1..6a16e2a9e 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -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; +} diff --git a/src/libpakfire/include/pakfire/cgroup.h b/src/libpakfire/include/pakfire/cgroup.h index f474faad8..cdbeb047c 100644 --- a/src/libpakfire/include/pakfire/cgroup.h +++ b/src/libpakfire/include/pakfire/cgroup.h @@ -24,6 +24,7 @@ #ifdef PAKFIRE_PRIVATE #include +#include #include @@ -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 */ diff --git a/tests/libpakfire/cgroup.c b/tests/libpakfire/cgroup.c index 8bd32c125..283cc0c68 100644 --- a/tests/libpakfire/cgroup.c +++ b/tests/libpakfire/cgroup.c @@ -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(); }