initctl: add CPU throttled information alongside memory usage

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2025-12-15 22:04:33 +01:00
parent 2681444b07
commit fb0ad18d3a
3 changed files with 65 additions and 1 deletions
+35
View File
@@ -252,6 +252,41 @@ uint64_t cgroup_memory(char *group)
return cgroup_uint64(path, "memory.current");
}
int cgroup_throttle(char *group, uint64_t *throttled_usec, uint64_t *nr_throttled)
{
char path[256];
char buf[256];
FILE *fp;
int found = 0;
paste(path, sizeof(path), FINIT_CGPATH, group);
fp = fopenf("r", "%s/cpu.stat", path);
if (!fp)
return -1;
*throttled_usec = 0;
*nr_throttled = 0;
while (fgets(buf, sizeof(buf), fp)) {
chomp(buf);
if (!strncmp(buf, "throttled_usec", 14)) {
*throttled_usec = strtoull(&buf[15], NULL, 10);
found++;
} else if (!strncmp(buf, "nr_throttled", 12)) {
*nr_throttled = strtoull(&buf[13], NULL, 10);
found++;
}
if (found == 2)
break;
}
fclose(fp);
return 0;
}
static float cgroup_cpuload(struct cg *cg)
{
char fn[256];
+1
View File
@@ -58,6 +58,7 @@ char *pid_cmdline (int pid);
char *pid_cgroup (int pid);
uint64_t cgroup_memory(char *group);
int cgroup_throttle(char *group, uint64_t *throttled_usec, uint64_t *nr_throttled);
struct cg *cg_stats(char *path);
struct cg *cg_conf (char *path);
+29 -1
View File
@@ -1015,6 +1015,7 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
indent, svc_typestr(svc),
indent, svc->forking ? "true" : "false",
indent, svc_status(svc));
if (svc->state != SVC_RUNNING_STATE) {
int rc, sig;
@@ -1030,30 +1031,48 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
"%s \"exit\": { \"%s\": %d },\n",
indent, "signal", sig);
}
fprintf(fp,
"%s \"origin\": \"%s\",\n"
"%s \"command\": \"%s\",\n",
indent, svc->file[0] ? svc->file : "built-in",
indent, svc_command(svc, buf, sizeof(buf), 0));
svc_environ(svc, buf, sizeof(buf), 0);
if (buf[0])
fprintf(fp,
"%s \"environment\": \"%s\",\n", indent, buf);
svc_cond(svc, buf, sizeof(buf), 0);
if (buf[0])
fprintf(fp,
"%s \"condition\": %s,\n", indent, buf);
if (svc->manual)
fprintf(fp,
"%s \"starts\": %d,\n", indent, svc->once);
fprintf(fp,
"%s \"restarts\": %d,\n", indent, svc->restart_tot); /* XXX: add restart_cnt and restart_max */
/* Add memory information if cgroup support is available */
/* Add memory and CPU information if cgroup support is available */
if (cgrp && svc->pid > 1) {
char *group = pid_cgroup(svc->pid);
if (group) {
uint64_t throttled_usec = 0;
uint64_t nr_throttled = 0;
fprintf(fp, "%s \"cgroup\": \"%s\",\n", indent, group);
fprintf(fp, "%s \"memory\": %lu,\n", indent, cgroup_memory(group));
if (cgroup_throttle(group, &throttled_usec, &nr_throttled) == 0) {
fprintf(fp, "%s \"cpu\": {\n", indent);
fprintf(fp, "%s \"throttled_usec\": %lu,\n", indent, throttled_usec);
fprintf(fp, "%s \"nr_throttled\": %lu\n", indent, nr_throttled);
fprintf(fp, "%s },\n", indent);
}
free(group);
}
}
@@ -1144,8 +1163,11 @@ static int show_status(char *arg)
printf(" Starts : %d\n", svc->once);
printf(" Restarts : %d (%d/%d)\n", svc->restart_tot, svc->restart_cnt, svc->restart_max);
printf(" Runlevels : %s\n", runlevel_string(runlevel, svc->runlevels));
if (cgrp && svc->pid > 1) {
const struct cg *cg;
uint64_t throttled_usec = 0;
uint64_t nr_throttled = 0;
char path[256];
char *group;
@@ -1157,6 +1179,12 @@ static int show_status(char *arg)
cg = cg_conf(path);
printf(" Memory : %s\n", memsz(cgroup_memory(group), uptm, sizeof(uptm)));
if (cgroup_throttle(group, &throttled_usec, &nr_throttled) == 0) {
printf("CPU Throttle : %lu usec (%lu times)\n",
throttled_usec, nr_throttled);
}
printf(" CGroup : %s cpu %s [%s, %s] mem [%s, %s]\n",
group, cg->cg_cpu.set, cg->cg_cpu.weight, cg->cg_cpu.max,
cg->cg_mem.min, cg->cg_mem.max);