cpu-sched: Support cpu affinity pinning for App 94/288094/10
authorUnsung Lee <unsung.lee@samsung.com>
Thu, 9 Feb 2023 02:32:19 +0000 (11:32 +0900)
committerUnsung Lee <unsung.lee@samsung.com>
Wed, 15 Feb 2023 07:02:44 +0000 (16:02 +0900)
This patch includes:
  - Parse configuration(s) of per app cpu affinity (config-parser.c/h)
  - Update of README to reflect per App cpu affinity (README)
  - Register cpu affinity fixed app in the list (cpu-sched.c)
  - Read /sys/devices/system/cpu/online to know onlie cpuset and
reflect the current online cpuset info to cpuset cgroup

Per app cpu affinity pinning is different from foreground cpu affinity
  - foreground cpu affinity: pinning cpu affinity for foreground status apps
    * foreground app status detect -> pinning cpu affinity
  - per App cpu affinity: pinning cpu affinity for fixed apps
  regardless of app status
* app launch detect -> pinning cpu affinity

Change-Id: Ibef926c5b40049ce00b97cf2ba74f83784efdccd
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
conf/README
src/common/conf/config-parser.c
src/common/conf/config-parser.h
src/common/proc-common.h
src/resource-optimizer/cpu/cpu-sched.c

index 960b6dc..8fba6a4 100644 (file)
@@ -543,6 +543,11 @@ Value: (strong|medium|weak)
 Comment: Specify the boosting level of this app/service/process.
 Example: CpuBoostingLevel=medium
 
+Key: CpuAffinity
+Value: (cpu id|min cpu id-max cpu id|cpu_id,cpu_id)
+Comment: Specify the cpu affinity of this app
+Example: CpuAffinity=1,3-5,8
+
 8. process.conf.d/*.conf
 ========================
 
index 684ecc5..3a60e99 100644 (file)
@@ -883,6 +883,22 @@ static int vendor_config(struct parse_result *result, void *user_data)
 
                pci->cpu_boosting_level = config_parse_boosting_level(result->value);
        }
+       else if (!strncmp(result->name, CPU_AFFINITY_NAME_CONF, strlen(CPU_AFFINITY_NAME_CONF) + 1)
+                       && *config_type == OPTIMIZER_CONFIG) {
+               if (!pci) {
+                       _E("process configuration information pointer should not be NULL");
+                       return RESOURCED_ERROR_FAIL;
+               }
+
+               if (cpu_sched_parse_cpuset(&pci->cpuset_info, result->value) < 0) {
+                       _E("invalid cpu affinity value (%s)", result->value);
+
+                       if (pci->cpuset_info.cpu_info != NULL)
+                               g_slist_free_full(pci->cpuset_info.cpu_info, free);
+                       pci->cpuset_info.cpu_info = NULL;
+                       return RESOURCED_ERROR_INVALID_PARAMETER;
+               }
+       }
 /*     else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
                                strlen(CPU_RT_RUN_TIME_NAME_CONF)+1) &&
                        *config_type == OPTIMIZER_CONFIG) {
index 064fb72..60d1642 100644 (file)
@@ -116,6 +116,7 @@ extern "C" {
 #define        COMPACTION_ENABLE_NAME_CONF                  "CompactionEnable"
 #define FRAG_LEVEL_NAME_CONF                         "FragLevel"
 #define FOREGROUND_APPS_NAME_CONF                    "ForegroundApps"
+#define CPU_AFFINITY_NAME_CONF                       "CpuAffinity"
 
 /* configuration value */
 #define CGROUP_LOW_VALUE_CONF                        "lowest"
index 18f107a..5a00c71 100644 (file)
@@ -67,6 +67,7 @@ struct proc_conf_info {
        enum proc_action fail_action;           /* release action */
        struct mem_action mem_action;
        struct cpu_sched_info cpu_sched_info;
+       struct cpuset_info cpuset_info;
        bool memory_throttling_enable;
        bool cpu_throttling_enable;
        cpu_boosting_level_e cpu_boosting_level;
index 0486b02..b22f4b2 100644 (file)
@@ -19,6 +19,7 @@
 #define GLOBAL_RT_PERIOD_US_PATH       "/proc/sys/kernel/sched_rt_period_us"
 #define GLOBAL_RT_RUNTIME_US_PATH      "/proc/sys/kernel/sched_rt_runtime_us"
 #define CPU_SCHED_FEATURE_PATH         "/sys/kernel/debug/sched_features"
+#define ONLINE_CPU_PATH                "/sys/devices/system/cpu/online"
 
 struct cpu_sched {
        struct cpuset_info *fg;
@@ -28,6 +29,8 @@ struct cpu_sched {
 
 static struct cpu_sched cs;
 
+static int cpu_sched_cpu_on(void *data);
+
 struct cpuset_info *cpu_sched_find_coreset(const char *name)
 {
        GSList *i;
@@ -78,7 +81,9 @@ static int cpu_sched_init_cgroup_set(const struct cpuset_info *set)
        int r;
        char buf[512];
 
-       assert(set);
+       if (set == NULL)
+               return 0;
+
        assert(set->name);
 
        r = cgroup_make_subdir(CPUSET_CGROUP, set->name, NULL);
@@ -101,6 +106,45 @@ static int cpu_sched_init_cgroup_set(const struct cpuset_info *set)
        return 0;
 }
 
+static int cpu_sched_init_cpu_online_info(void)
+{
+       int ret;
+       GSList *item;
+       struct cpuset_info cpuset_info = {0, };
+       _cleanup_free_ char *buf = NULL;
+
+       buf = calloc(1, PATH_MAX);
+       if (!buf)
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
+
+       /* Read the current online cpus */
+       ret = fread_str(ONLINE_CPU_PATH, &buf);
+       if (ret < 0) {
+               _E("[CPU-SCHED] failed to read online cpu");
+               return ret;
+       }
+
+       if (cpu_sched_parse_cpuset(&cpuset_info, buf) < 0) {
+               _E("invalid cpu affinity value (%s)", buf);
+
+               if (cpuset_info.cpu_info != NULL)
+                       g_slist_free_full(cpuset_info.cpu_info, free);
+
+               return RESOURCED_ERROR_FAIL;
+       }
+
+       /* Pin cpu affinity */
+       gslist_for_each_item(item, cpuset_info.cpu_info) {
+               struct cpu_info *cpu_info = (struct cpu_info *)item->data;
+               if (cpu_info == NULL)
+                       continue;
+
+               cpu_sched_cpu_on(&cpu_info->cpu_id);
+       }
+
+       return RESOURCED_ERROR_NONE;
+}
+
 /* init cpuset's cgroups */
 static int cpu_sched_init_cgroup(struct cpu_sched *cs)
 {
@@ -131,7 +175,13 @@ static int cpu_sched_init_cgroup(struct cpu_sched *cs)
                }
        }
 
-       return cs->fg ? cpu_sched_init_cgroup_set(cs->fg) : 0;
+       r = cpu_sched_init_cgroup_set(cs->fg);
+       if (r < 0) {
+               _E("cpu-set: error setting up cpuset (%s)", cs->fg->name);
+               return r;
+       }
+
+       return cpu_sched_init_cpu_online_info();
 }
 
 /* free memory allocated in cpuset_info structure */
@@ -164,35 +214,59 @@ static void cpu_sched_free_cpuset_full(void *data)
 static int load_cpu_affinity_config(struct cpu_sched *data)
 {
        char *name;
-       bool is_fg;
+       gpointer app_name;
+       gpointer proc_conf_ptr;
+       GHashTableIter app_list_iter;
 
        assert(data);
 
-       if (!get_cpu_affinity_conf_name())
-               return RESOURCED_ERROR_NONE;
+       if (get_cpu_affinity_conf_name() == NULL)
+               goto cpu_affinity_set_for_fixed_app;
 
        name = strdup(get_cpu_affinity_conf_name());
-       is_fg = !strcmp(name, FOREGROUND_APPS_NAME_CONF);
+       if (!name || strcmp(name, FOREGROUND_APPS_NAME_CONF)) {
+               _E("[CPU-SCHED] Failed to allocate memory during making a duplicate name or wrong name (%s)",
+                               get_cpu_affinity_conf_name());
+               goto cpu_affinity_set_for_fixed_app;
+       }
 
        struct cpuset_info *cpuset_info = (struct cpuset_info *)calloc(1, sizeof *cpuset_info);
        if (cpuset_info == NULL) {
                free(name);
-               return RESOURCED_ERROR_OUT_OF_MEMORY;
+               _E("[CPU_SCHED] Failed to allocate memory");
+               goto cpu_affinity_set_for_fixed_app;
        }
 
        cpuset_info->name = name;
 
-       if (cpu_sched_parse_cpuset(cpuset_info, get_cpu_affinity_conf_value()) < 0) {
+       if (!get_cpu_affinity_conf_value() ||
+                       cpu_sched_parse_cpuset(cpuset_info, get_cpu_affinity_conf_value()) < 0) {
                cpu_sched_free_cpuset(&cpuset_info);
-               return RESOURCED_ERROR_FAIL;
+               goto cpu_affinity_set_for_fixed_app;
        }
 
-       if (is_fg)
-               data->fg = cpuset_info;
-       else
-               data->apps = g_slist_append(data->apps, cpuset_info);
+       data->fg = cpuset_info;
 
+cpu_affinity_set_for_fixed_app:
+       /* Free memory if previously allocated memory for 'ForegroundApps' exists */
        free_cpu_affinity_conf();
+
+       /* Register static fixed cpu affinity apps */
+       g_hash_table_iter_init(&app_list_iter, fixed_app_list_get());
+       while (g_hash_table_iter_next(&app_list_iter, &app_name, &proc_conf_ptr)) {
+               struct proc_conf_info *pci = (struct proc_conf_info *)proc_conf_ptr;
+
+               if (!pci) {
+                       _W("[CPU-SCHED] Process configuration information is NULL");
+                       continue;
+               }
+
+               if (pci->cpuset_info.cpu_info) {
+                       pci->cpuset_info.name = pci->name;
+                       data->apps = g_slist_append(data->apps, &pci->cpuset_info);
+               }
+       }
+
        return RESOURCED_ERROR_NONE;
 }