pass: cpuhp: Replace legacy monitoring with RESMON (Resource Monitor) 50/170450/4
authorChanwoo Choi <cw00.choi@samsung.com>
Mon, 12 Feb 2018 05:06:54 +0000 (14:06 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 15 Mar 2018 06:03:44 +0000 (15:03 +0900)
PASS CPUHP (CPU Hotplug Manager) module requires the CPU resource
monitoring in order to check the current system status and then
decide the optimal amount of CPU resource. It makes the balance
between the ondemand peformanace and required low-power consumption.

But, CPUHP used the legacy and too tightly coupled monitoring code.
So, replace the legacy method for resource monitoring with RESMON
(Resource Monitor). CPUHP will use the RESMON_CPUHP type instead of
old method.

Change-Id: I1dbbafceeb1c747383fdbfe0aa33c3e84fe02a68
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
src/pass/pass-cpuhp-radiation.c
src/pass/pass-cpuhp-step.c
src/pass/pass-cpuhp.c
src/pass/pass-hal.c
src/pass/pass-hal.h
src/pass/pass-parser.c
src/pass/pass.h

index 649385b..8010c39 100644 (file)
 #include <stdlib.h>
 
 #include "pass.h"
+#include "pass-resmon.h"
+
+#define PASS_CPU_STATS_MAX_COUNT       20
 
 /*
  * pass_cpuhp_radiation_governor - Check cpu state and determine the amount of resource
  *
- * @stats: structure for getting cpu frequency state from kerncel
+ * @res: the instance of struct pass_resource.
+ * @result: the result of resource monitoring.
  *
  * This function check periodically current following state of system
  * and then determine whether pass level up or down according to pass
  * - the number of nr_running
  * - the number of busy_cpu
  */
-int pass_cpuhp_radiation_governor(struct pass_resource *res)
+int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result)
 {
        struct pass_level *levels = res->config_data.levels;
        struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
+       struct resmon_result_src_cpuhp *cpu_stats = result;
        int up_threshold = cpuhp->up_threshold;
        int down_threshold = cpuhp->down_threshold;
        int num_pass_gov = 0;
@@ -58,7 +62,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res)
        int j;
        int64_t time;
 
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+       for (i = 0; i < PASS_CPU_STATS_MAX_COUNT; i++) {
                time = cpu_stats[i].time;
                freq = cpu_stats[i].freq;
                nr_running = cpu_stats[i].nr_runnings;
@@ -192,7 +196,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res)
 
        /*
        if (level == res->prev_level) {
-               for (i = num_pass_gov; i < cpuhp->num_pass_cpu_stats; i++) {
+               for (i = num_pass_gov; i < PASS_CPU_STATS_MAX_COUNT; i++) {
                        time = cpu_stats[i].time;
                        freq = cpu_stats[i].freq;
                        nr_running = cpu_stats[i].nr_runnings;
index 606d217..a86a030 100644 (file)
 #include <stdlib.h>
 
 #include "pass.h"
+#include "pass-resmon.h"
+
+#define PASS_CPU_STATS_MAX_COUNT       20
 
 /*
  * pass_cpuhp_step_governor - Check cpu state and determine the amount of resource
  *
- * @stats: structure for getting cpu frequency state from kerncel
+ * @res: the instance of struct pass_resource.
+ * @result: the result of resource monitoring.
  *
  * This function check periodically current following state of system
  * and then determine whether pass level up or down according to pass
  * - the number of nr_running
  * - the number of busy_cpu
  */
-int pass_cpuhp_step_governor(struct pass_resource *res)
+int pass_cpuhp_step_governor(struct pass_resource *res, void *result)
 {
        struct pass_level *levels = res->config_data.levels;
        struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
+       struct resmon_result_src_cpuhp *cpu_stats = result;
        int up_threshold = cpuhp->up_threshold;
        int down_threshold = cpuhp->down_threshold;
        int num_pass_gov = 0;
@@ -55,7 +59,7 @@ int pass_cpuhp_step_governor(struct pass_resource *res)
        int j;
        int64_t time;
 
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+       for (i = 0; i < PASS_CPU_STATS_MAX_COUNT; i++) {
                time = cpu_stats[i].time;
                freq = cpu_stats[i].freq;
                nr_running = cpu_stats[i].nr_runnings;
index 38174a4..7954ef8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PASS (Power Aware System Service) Governor
+ * PASS (Power Aware System Service) CPUHP (CPU Hotplug Manager)
  *
  * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
  *
 #include <pass/config-parser.h>
 
 #include "pass.h"
-#include "pass-hal.h"
 #include "pass-rescon.h"
+#include "pass-resmon.h"
 
-extern int pass_cpuhp_step_governor(struct pass_resource *res);
-extern int pass_cpuhp_radiation_governor(struct pass_resource *res);
+extern int pass_cpuhp_step_governor(struct pass_resource *res, void *result);
+extern int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result);
 static int cpuhp_governor_update(struct pass_resource *, enum pass_state);
 
 #define PASS_DEFAULT_CPU_THRESHOLD             20
@@ -44,7 +44,7 @@ struct pass_cpuhp_governor {
        int (*init)(struct pass_resource *res);
        int (*exit)(struct pass_resource *res);
        int (*update)(struct pass_resource *res, enum pass_state state);
-       int (*governor)(struct pass_resource *res);
+       int (*governor)(struct pass_resource *res, void *result);
 };
 
 static bool is_enabled(struct pass_cpuhp *cpuhp)
@@ -102,12 +102,12 @@ static struct pass_hotplug* cpuhp_get_hotplug(struct pass_resource *res,
        return NULL;
 }
 
-static void cpuhp_calculate_busy_cpu(struct pass_resource *res)
+static void cpuhp_calculate_busy_cpu(struct pass_resource *res, void *result)
 {
        struct pass_cpuhp *cpuhp = &res->cpuhp;
        struct pass_level *levels = res->config_data.levels;
        struct pass_resource_config_data *config_data = &res->config_data;
-       struct pass_cpu_stats *stats = cpuhp->pass_cpu_stats;
+       struct resmon_result_src_cpuhp *stats = result;
        unsigned int level = res->rescon.curr_level;
        unsigned int cpu_threshold = 0;
        unsigned int busy_cpu;
@@ -122,7 +122,7 @@ static void cpuhp_calculate_busy_cpu(struct pass_resource *res)
 
        limit_min_cpu = levels[level].limit_min_cpu;
 
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+       for (i = 0; i < PASS_CPU_STATS_MAX_COUNT; i++) {
                cur_freq = stats[i].freq;
                nr_runnings = stats[i].nr_runnings;
 
@@ -164,14 +164,13 @@ static void cpuhp_calculate_busy_cpu(struct pass_resource *res)
        }
 }
 
-static gboolean cpuhp_governor_timer_cb(gpointer data)
+static int cpuhp_timer_func(void *result, void *user_data)
 {
-       struct pass_resource *res = (struct pass_resource *)data;
+       struct pass_resource *res = user_data;
        struct pass_level *levels;
        struct pass_cpuhp *cpuhp;
-       static int count = 0;
        double curr_gov_timeout, next_gov_timeout;
-       int level, ret;
+       int level;
 
        if (!res) {
                _E("cannot call the governor timeout callback\n");
@@ -181,34 +180,15 @@ static gboolean cpuhp_governor_timer_cb(gpointer data)
        levels = res->config_data.levels;
        cpuhp = &res->cpuhp;
 
-       /*
-        * Collect data related to system state
-        * - the current frequency
-        * - the number of nr_running
-        * - the resource utilization
-        */
-       ret = pass_get_cpu_stats(res);
-       if (ret < 0) {
-               if (count++ < PASS_CPU_STATS_MAX_COUNT)
-                       return TRUE;
-
-               count = 0;
-
-               _E("cannot read the 'pass_cpu_stats' sysfs entry");
-               cpuhp_governor_update(res, PASS_OFF);
-
-               return FALSE;
-       }
-
        /* Calculate the number of busy cpu */
-       cpuhp_calculate_busy_cpu(res);
+       cpuhp_calculate_busy_cpu(res, result);
 
        /* Store current governor timeout */
        curr_gov_timeout = levels[res->rescon.curr_level].gov_timeout;
 
        /* Determine the amount of proper resource */
        if (cpuhp->governor->governor) {
-               level = cpuhp->governor->governor(res);
+               level = cpuhp->governor->governor(res, result);
 
                pass_rescon_set_level(res, level);
        } else {
@@ -228,11 +208,9 @@ static gboolean cpuhp_governor_timer_cb(gpointer data)
                _I("Change the period of governor timer from %fs to %fs\n",
                                curr_gov_timeout,
                                next_gov_timeout);
-               g_source_remove(cpuhp->gov_timeout_id);
-               cpuhp->gov_timeout_id = g_timeout_add(
-                               (guint)(next_gov_timeout * 1000),
-                               cpuhp_governor_timer_cb,
-                               (gpointer)res);
+
+               pass_resmon_update_timer_interval(res, RESMON_SRC_CPUHP,
+                                               next_gov_timeout * 1000);
        }
 
        return TRUE;
@@ -241,6 +219,7 @@ static gboolean cpuhp_governor_timer_cb(gpointer data)
 static void cpuhp_governor_start(struct pass_resource *res)
 {
        struct pass_cpuhp *cpuhp = &res->cpuhp;
+       int ret;
 
        if (!cpuhp->governor) {
                _E("cannot start PASS governor");
@@ -252,19 +231,15 @@ static void cpuhp_governor_start(struct pass_resource *res)
                return;
        }
 
-       /* Add callback function for each governor timeout */
-       if (res->config_data.gov_timeout > 0) {
-               cpuhp->gov_timeout_id = g_timeout_add(
-                               (guint)(res->config_data.gov_timeout * 1000),
-                               (GSourceFunc)cpuhp_governor_timer_cb,
-                               (gpointer)res);
-               if (!cpuhp->gov_timeout_id) {
-                       _E("cannot add core timer for governor");
-                       cpuhp_governor_update(res, PASS_OFF);
-                       return;
-               }
-       } else {
-               cpuhp->gov_timeout_id = 0;
+       /* Register the resource-monitor for CPUHP module */
+       ret = pass_resmon_register_timer(res, RESMON_SRC_CPUHP,
+                       RESMON_TIMER_PERIODIC,
+                       res->config_data.gov_timeout * 1000,
+                       cpuhp_timer_func,
+                       res);
+       if (ret < 0) {
+               _E("failed to register timer for CPUHP\n");
+               return;
        }
 
        /*
@@ -279,14 +254,11 @@ static void cpuhp_governor_start(struct pass_resource *res)
 
        /* Set PASS state as PASS_ON */
        cpuhp->state = PASS_ON;
-
-       _I("Start governor for '%s' resource", res->config_data.res_name);
 }
 
 static void cpuhp_governor_stop(struct pass_resource *res)
 {
        struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_resource_config_data *config_data = &res->config_data;
 
        if (!cpuhp->governor) {
                _E("cannot stop PASS governor");
@@ -300,15 +272,11 @@ static void cpuhp_governor_stop(struct pass_resource *res)
 
        cpuhp_hotplug_stop(res);
 
-       if (cpuhp->gov_timeout_id) {
-               g_source_remove(cpuhp->gov_timeout_id);
-               cpuhp->gov_timeout_id = 0;
-       }
+       /* Unregister the resource-monitor for CPUHP module */
+       pass_resmon_unregister_timer(res, RESMON_SRC_CPUHP);
 
        /* Set PASS state as PASS_OFF */
        cpuhp->state = PASS_OFF;
-
-       _I("Stop governor for '%s' resource", config_data->res_name);
 }
 
 static int cpuhp_governor_init(struct pass_resource *res)
@@ -333,7 +301,6 @@ static int cpuhp_governor_init(struct pass_resource *res)
 static int cpuhp_governor_exit(struct pass_resource *res)
 {
        struct pass_cpuhp *cpuhp = &res->cpuhp;
-       int i;
 
        /*
         * Stop timer and
@@ -341,14 +308,6 @@ static int cpuhp_governor_exit(struct pass_resource *res)
         */
        cpuhp_governor_update(res, PASS_OFF);
 
-       /* Free allocated memory */
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               free(cpuhp->pass_cpu_stats[i].load);
-               free(cpuhp->pass_cpu_stats[i].nr_running);
-               free(cpuhp->pass_cpu_stats[i].runnable_load);
-       }
-       free(cpuhp->pass_cpu_stats);
-
        if (cpuhp->hotplug)
                free(cpuhp->hotplug->sequence);
 
@@ -356,7 +315,6 @@ static int cpuhp_governor_exit(struct pass_resource *res)
        cpuhp->pass_cpu_threshold = 0;
        cpuhp->up_threshold = 0;
        cpuhp->down_threshold = 0;
-       cpuhp->num_pass_cpu_stats = 0;
        cpuhp->governor = NULL;
 
        return 0;
@@ -452,6 +410,21 @@ int pass_cpuhp_init(struct pass_resource *res)
        if (!res)
                return -EINVAL;
 
+       /*
+        * FIXME: The h/w resource configuration specifies the gov_type.
+        * When gov_type is either PASS_GOV_STEP(2) or PASS_GOV_RADIATION(3),
+        * CPUHP should be enabled. On later, each PASS module have to define
+        * the separate property in configuration which indicates either this
+        * module is used or not.
+        */
+       switch (res->config_data.gov_type) {
+       case PASS_GOV_STEP:
+       case PASS_GOV_RADIATION:
+               break;
+       default:
+               return 0;
+       };
+
        cpuhp = &res->cpuhp;
 
        if (!cpuhp->pass_cpu_threshold)
@@ -463,27 +436,11 @@ int pass_cpuhp_init(struct pass_resource *res)
        if (!cpuhp->down_threshold)
                cpuhp->down_threshold = PASS_DEFAULT_LEVEL_DOWN_THRESHOLD;
 
-       if (!cpuhp->num_pass_cpu_stats)
-               cpuhp->num_pass_cpu_stats = PASS_CPU_STATS_MAX_COUNT;
-
        for (i = 0; i < res->config_data.num_levels; i++)
                if (max_freq < res->config_data.levels[i].limit_max_freq)
                        max_freq = res->config_data.levels[i].limit_max_freq;
        cpuhp->max_freq = max_freq;
 
-       /* Allocate memory according to the number of data and cpu */
-       cpuhp->pass_cpu_stats = calloc(cpuhp->num_pass_cpu_stats,
-                                       sizeof(struct pass_cpu_stats));
-
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               cpuhp->pass_cpu_stats[i].load =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-               cpuhp->pass_cpu_stats[i].nr_running =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-               cpuhp->pass_cpu_stats[i].runnable_load =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-       }
-
        /* Get the instance of CPU Hotplug's policy */
        cpuhp->hotplug = cpuhp_get_hotplug(res, res->config_data.gov_type);
        if (cpuhp->hotplug) {
index 73eeb17..3694326 100644 (file)
@@ -849,62 +849,3 @@ int pass_put_resource(struct pass_resource *res)
 
        return 0;
 }
-/*
- * FXIME: Following function is not standard interface.
- * Following functions will be altered by the standard interface on later.
- *
- * - int pass_get_cpu_stats(struct pass_resource *res)
- * - int64_t pass_get_time_ms(void)
- */
-
-/* Get the load_table of each resource to estimate the system load. */
-int pass_get_cpu_stats(struct pass_resource *res)
-{
-       struct pass_cpu_stats *stats;
-       char str[BUFF_MAX];
-       FILE *fp_stats = NULL;
-       int i, j, ret;
-
-       if (!res)
-               return -EINVAL;
-       stats = res->cpuhp.pass_cpu_stats;
-
-       if (!stats) {
-               _E("invalid parameter of structure pass_cpu_stats");
-               return -EINVAL;
-       }
-
-       fp_stats = fopen(res->config_data.path_load_table, "r");
-       if (fp_stats == NULL)
-               return -EIO;
-
-       /* Read the title and drop the buffer because it is not used */
-       if (!fgets(str, BUFF_MAX, fp_stats)) {
-               fclose(fp_stats);
-               return -EIO;
-       }
-
-       for (i = 0; i < res->cpuhp.num_pass_cpu_stats; i++) {
-               ret = fscanf(fp_stats, "%" SCNd64 "%u %u %u",
-                       &stats[i].time,
-                       &stats[i].freq,
-                       &stats[i].freq_new,
-                       &stats[i].nr_runnings);
-               if (ret < 0) {
-                       fclose(fp_stats);
-                       return -EIO;
-               }
-
-               for (j = 0; j < res->config_data.num_cpus; j++) {
-                       ret = fscanf(fp_stats, "%u", &stats[i].load[j]);
-                       if (ret < 0) {
-                               fclose(fp_stats);
-                               return -EIO;
-                       }
-               }
-       }
-
-       fclose(fp_stats);
-
-       return 0;
-}
index 8d1fd6f..da47a49 100644 (file)
@@ -75,11 +75,6 @@ int pass_set_online_min_num(struct pass_resource *res, int num);
 /* Get and set the maximum number of online CPUs */
 int pass_get_online_max_num(struct pass_resource *res);
 int pass_set_online_max_num(struct pass_resource *res, int num);
-/*
- * FXIME: Following function is not standard interface.
- * These functions will be altered by the standard interface on later.
- */
-int pass_get_cpu_stats(struct pass_resource *res);
 
 /***
  * Functions for Memory h/w resource
index 911a188..37b4595 100644 (file)
@@ -250,8 +250,6 @@ static int parse_core(struct parse_result *result, void *user_data)
        else if (MATCH(result->name, "pass_init_level"))
                res->rescon.init_level = atoi(result->value);
 
-       else if (MATCH(result->name, "pass_num_cpu_stats"))
-               res->cpuhp.num_pass_cpu_stats = atoi(result->value);
        else if (MATCH(result->name, "pass_cpu_threshold"))
                res->cpuhp.pass_cpu_threshold = atoi(result->value);
        else if (MATCH(result->name, "pass_up_threshold"))
@@ -567,7 +565,6 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path)
        res->rescon.max_level = 0;
 
        /* Initialize the CPUHP's data */
-       cpuhp->num_pass_cpu_stats = 0;
        cpuhp->pass_cpu_threshold = 0;
        cpuhp->up_threshold = 0;
        cpuhp->down_threshold = 0;
index 58fcf20..9c42ce3 100644 (file)
@@ -63,25 +63,6 @@ enum pass_state {
        PASS_ON = 1,
 };
 
-struct pass_cpu_stats {
-       const char *path;
-
-       int64_t time;
-       unsigned int freq;
-       unsigned int freq_new;
-       unsigned int nr_runnings;
-
-       unsigned int *load;
-       unsigned int *nr_running;
-       unsigned int *runnable_load;
-
-       unsigned int num_busy_cpu;
-       unsigned int avg_load;
-       unsigned int avg_runnable_load;
-       unsigned int avg_thread_load;
-       unsigned int avg_thread_runnable_load;
-};
-
 struct pass_hotplug {
        char name[BUFF_MAX];
        unsigned int num_cpus;
@@ -252,11 +233,8 @@ struct pass_pmqos {
  * @pass_cpu_threshold:
  * @up_threshold: the threshold used when increasing the level
  * @down_threshold: the threshold used when decreasing the level
- * @num_pass_cpu_stats: the number of history for CPU utilization/nr_runnings
- * @pass_cpu_stats: the list of CPU utilization/nr_runnings
  * @last_time: the updated last time of cpu_stats
  * @governor: the instance of CPUHP Policy governor.
- * @gov_timeout_id: the periodic timer id
  * @max_freq: the maximum frequency among levels
  *
  * @hotplug: the instance of CPU Hotplug governor (will be deprecated).
@@ -270,13 +248,9 @@ struct pass_cpuhp {
        unsigned int up_threshold;
        unsigned int down_threshold;
 
-       int num_pass_cpu_stats;
-       struct pass_cpu_stats *pass_cpu_stats;
-
        int64_t last_time;
 
        struct pass_cpuhp_governor *governor;
-       guint gov_timeout_id;
 
        unsigned int max_freq;