cpu-sched: foreground core set data structures 63/236963/6
authorMaciej Słodczyk <m.slodczyk2@partner.samsung.com>
Tue, 23 Jun 2020 18:46:11 +0000 (20:46 +0200)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Tue, 21 Jul 2020 11:56:10 +0000 (11:56 +0000)
Change-Id: I2bd110e85d7ebc8f30f0b7949abccbbb92cd6881
Signed-off-by: Maciej Słodczyk <m.slodczyk2@partner.samsung.com>
src/cpu/cpu-sched.c
src/cpu/cpu-sched.conf

index 0c81506..4a42c7e 100644 (file)
 #include "module.h"
 #include "macro.h"
 #include "resourced.h"
+#include "config-parser.h"
+#include "trace.h"
+#include "cgroup.h"
+
+#define CPU_SCHED_CONF_FILE     RD_CONFIG_FILE(cpu-sched)
+#define CPU_SCHED_FG_NAME      "foreground"
+#define MOUNTS_PATH            "/proc/mounts"
+#define CPUSET_CGROUP          "/sys/fs/cgroup/cpuset"
+
+
+struct core {
+       int id;
+       bool on;
+};
+
+struct coreset {
+       GSList *cores;
+       char *name;
+};
+
+struct cpu_sched {
+       struct coreset fg;
+       bool is_initalized;
+};
+
+static struct cpu_sched cs;
+
+/* check if cpuset subsystem is mounted at the right location */
+static bool cpu_sched_is_cpuset_mounted()
+{
+       FILE *f;
+       ssize_t r;
+       size_t len = 0;
+       char *buf = NULL;
+       char mountpoint[128], opts[128];
+       bool ret = false;
+
+       f = fopen(MOUNTS_PATH, "r");
+       if (NULL == f) {
+               _E("cpu-sched: could not open " MOUNTS_PATH);
+               return ret;
+       }
+
+       while ((r = getline(&buf, &len, f)) != -1) {
+               if (sscanf(buf, "%*s %127s %*s %127s %*d %*d", mountpoint, opts) != 2)
+                       continue;
+
+               if (!strcmp(mountpoint, CPUSET_CGROUP) && NULL != strstr(opts, "cpuset")) {
+                       ret = true;
+                       break;
+               }
+       }
+
+       free(buf);
+       fclose(f);
+
+       return ret;
+}
+
+static int cpu_sched_init_cgroup_set(const struct coreset *set)
+{
+       int r;
+       char buf[512];
+
+       assert(set);
+       assert(set->name);
+
+       _D("cpu-sched: init cgroup set for %s", set->name);
+       r = cgroup_make_subdir(CPUSET_CGROUP, set->name, NULL);
+       if (r < 0) {
+               _E("failed to make cpuset cgroup (%s)", set->name);
+               return r;
+       }
+
+       r = snprintf(buf, sizeof buf, "%s/%s", CPUSET_CGROUP, set->name);
+       if (r < 0) {
+               _E("failed to setup memory nodes for cpuset (%s)", set->name);
+               return r;
+       }
+
+       /* don't force any memory nodes with this cpuset */
+       r = cgroup_write_node_uint32(buf, "cpuset.mems", 0);
+       ret_value_msg_if(r < 0, r,
+               "Failed to reset memory nodes for cpuset: %m");
+
+       return 0;
+}
+
+/* init cpuset's cgroups */
+static int cpu_sched_init_cgroup(struct cpu_sched *cs)
+{
+       int r;
+
+       _D("cpu-sched: init cgroup subsystem");
+       if (false == cpu_sched_is_cpuset_mounted()) {
+               r = cgroup_make_subdir(DEFAULT_CGROUP, "cpuset", NULL);
+               if (r < 0) {
+                       _E("failed to make cpuset cgroup");
+                       return r;
+               }
+
+               r = cgroup_mount_subsystem("cpuset", CPUSET_CGROUP, "cpuset");
+               if (r < 0) {
+                       _E("failed to mount cpuset cgroup: %m");
+                       return r;
+               }
+       }
+
+       return cpu_sched_init_cgroup_set(&cs->fg);
+}
+
+/* create single core struct representation */
+static int cpu_sched_new_core(struct coreset *set, int core_id)
+{
+       struct core *c;
+
+       assert(set);
+       assert(core_id >= 0);
+
+       _D("cpu-sched: new core %d for set %s", core_id, set->name);
+       c = (struct core *)calloc(1, sizeof *c);
+       if (NULL == c) {
+               _E("cpu-sched: could not allocate memory for core struct");
+               return RESOURCED_ERROR_FAIL;
+       }
+       c->id = core_id;
+       c->on = false;
+
+       set->cores = g_slist_append(set->cores, c);
+       return RESOURCED_ERROR_NONE;
+}
+
+/* free memory allocated in coreset structure */
+static void cpu_sched_free_cpuset(struct coreset *set)
+{
+       if (NULL != set->cores)
+               g_slist_free_full(set->cores, free);
+       set->cores = NULL;
+
+       free(set->name);
+       set->name = NULL;
+}
+
+/* parse config for specific coreset line */
+static int cpu_sched_parse_cpuset(struct coreset *set, char *value)
+{
+       char *ptr, *saveptr;
+       int min, max;
+       int r;
+
+       assert(set);
+       assert(value);
+       assert(!set->cores);
+       _D("cpu-sched: parse cpuset for %s (%s)", set->name, value);
+
+       ptr = strtok_r(value, ",", &saveptr);
+       while (ptr) {
+               if (NULL == strstr(ptr, "-")) { /* single value */
+                       r = sscanf(ptr, "%d", &min);
+                       if (r == 1 && min >= 0) {
+                               if (RESOURCED_ERROR_NONE != cpu_sched_new_core(set, min))
+                                       goto parse_cpuset_fail;
+                       } else {
+                               _E("cpu-sched: error parsing cpuset (%s)", ptr);
+                               goto parse_cpuset_fail;
+                       }
+               } else { /* range */
+                       r = sscanf(ptr, "%d-%d", &min, &max);
+                       if (r == 2 && min >= 0 && max >= 0 && max > min) {
+                               for (int i = min; i <= max; i++) {
+                                       if (RESOURCED_ERROR_NONE != cpu_sched_new_core(set, i))
+                                               goto parse_cpuset_fail;
+                               }
+                       } else {
+                               _E("cpu-sched: error parsing cpuset (%s)", ptr);
+                               goto parse_cpuset_fail;
+                       }
+
+               }
+
+               ptr = strtok_r(NULL, ",", &saveptr);
+       }
+       return RESOURCED_ERROR_NONE;
+parse_cpuset_fail:
+       cpu_sched_free_cpuset(set);
+       return RESOURCED_ERROR_FAIL;
+}
+
+static int load_config(struct parse_result *result, void *user_data)
+{
+       int r;
+       struct cpu_sched *data = (struct cpu_sched *)user_data;
+
+       assert(data);
+
+       if (strcmp(result->name, CPU_SCHED_FG_NAME))
+               return RESOURCED_ERROR_NONE;
+
+       r = cpu_sched_parse_cpuset(&data->fg, result->value);
+
+       if (r < 0) {
+               _E("cpu-sched parse fg coreset: could not parse");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       data->fg.name = strdup(CPU_SCHED_FG_NAME);
+       return RESOURCED_ERROR_NONE;
+}
+
+static int cpu_sched_parse_config(struct cpu_sched *data)
+{
+       _D("cpu-sched: parse config");
+       if (config_parse(CPU_SCHED_CONF_FILE, load_config, data) < 0)
+               return RESOURCED_ERROR_FAIL;
+
+       return RESOURCED_ERROR_NONE;
+}
 
 static int cpu_sched_init(void *data)
 {
+       int r;
        _D("cpu-sched: init module");
+
+       if (cpu_sched_parse_config(&cs) != RESOURCED_ERROR_NONE) {
+               _E("cpu-sched: error parsing config");
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       r = cpu_sched_init_cgroup(&cs);
+       if (r < 0)
+               goto init_failed;
+
+       cs.is_initalized = true;
        return RESOURCED_ERROR_NONE;
+
+init_failed:
+       cpu_sched_free_cpuset(&cs.fg);
+       cs.is_initalized = false;
+       return RESOURCED_ERROR_FAIL;
 }
 
 static int cpu_sched_finalize(void *data)
 {
        _D("cpu-sched: deinit module");
+       cpu_sched_free_cpuset(&cs.fg);
+       cs.is_initalized = false;
        return RESOURCED_ERROR_NONE;
 }
 
index e69de29..1eac383 100644 (file)
@@ -0,0 +1 @@
+foreground=1,2,4-6