pass: resmon: Add timer-based RESMON_SRC_CPUHP source 48/170448/4
authorChanwoo Choi <cw00.choi@samsung.com>
Tue, 13 Feb 2018 07:00:39 +0000 (16:00 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 15 Mar 2018 06:03:41 +0000 (15:03 +0900)
RESMON_SRC_CPUHP indicates the CPU resource monitoring for CPUHP (CPU Hotplug
Manager) module. RESMON_CPUHP contains the CPU's information. They are used
to decide the current system status on CPUHP.

Unfortunately, it is nonstandard linux kernel interface which is developed
for only CPUHP module. It should be replaced with standard linux kernel
interface on later.

[Description of RESMON_CPUHP resource-monitor]
- The kind of resource data
: time (time unit is millisecond)
: old CPU frequency (Minimum/Maximum is different accroding to h/w board)
: new CPU frequency (Minimum/Maximum is different accroding to h/w board)
: the number of nr_running tasks in the same cluster (100 means the one task)
: each CPU's utilization (Minimum is 0 and maximum is 100)

- Path of RESMON_SRC_CPUHP monitoring
: /sys/kernel/debug/cpufreq/cpu0/load_table

- Result of RESMON_SRC_CPUHP monitoring
$ cat /sys/kernel/debug/cpufreq/cpu0/load_table
Time(ms)   Old Freq(Hz) New Freq(Hz) NR_running CPU0 CPU1 CPU2 CPU3
3417690    500000       500000       300        10   4    0    0
3417770    500000       500000       182        10   4    0    0

Change-Id: Idcb3384e507f08aac282e0f0629a5666d7e0dd75
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
src/pass/pass-resmon-source.c
src/pass/pass-resmon.h

index 270f5f8094b9149f00441357d79fb1735562a2e2..9c8efcb875058c27568437d2c868d5fa74ca3ccd 100644 (file)
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #include <pass/log.h>
 
 #include "pass.h"
@@ -39,18 +41,100 @@ static int resmon_thermal_timer_handler(struct resmon *monitor, void *result)
 }
 
 /* RESMON_SRC_CPUHP */
+#define RESMON_SRC_CPUHP_COUNT 20
 static int resmon_cpuhp_init(struct resmon *monitor)
 {
+       struct resmon_result_src_cpuhp *result;
+       int i;
+
+       if (monitor->result)
+               return 0;
+
+       result = calloc(RESMON_SRC_CPUHP_COUNT, sizeof(*result));
+
+       for (i = 0; i < RESMON_SRC_CPUHP_COUNT; i++) {
+               result[i].load = calloc(RESMON_SRC_CPUHP_COUNT,
+                                       sizeof(unsigned int));
+               result[i].nr_running = calloc(RESMON_SRC_CPUHP_COUNT,
+                                       sizeof(unsigned int));
+               result[i].runnable_load = calloc(RESMON_SRC_CPUHP_COUNT,
+                                       sizeof(unsigned int));
+       }
+
+       monitor->result = result;
+
        return 0;
 }
 
 static int resmon_cpuhp_exit(struct resmon *monitor)
 {
+       struct resmon_result_src_cpuhp *result;
+       int i;
+
+       if (!monitor->result)
+               return 0;
+
+       result = (struct resmon_result_src_cpuhp *)monitor->result;
+       if (!result)
+               return -ENOMEM;
+
+       for (i = 0; i < RESMON_SRC_CPUHP_COUNT; i++) {
+               free(result[i].load);
+               free(result[i].nr_running);
+               free(result[i].runnable_load);
+       }
+
+       free(monitor->result);
+       monitor->result = NULL;
+
        return 0;
 }
 
 static int resmon_cpuhp_timer_handler(struct resmon *monitor, void *result)
 {
+       struct pass_resmon *resmon = monitor->resmon;
+       struct pass_resource *res =
+                       container_of(resmon, struct pass_resource, resmon);
+       struct resmon_result_src_cpuhp *cpuhp_result = result;
+       char str[BUFF_MAX];
+       int i, j, ret;
+       FILE *fp = NULL;
+
+       if (!cpuhp_result)
+               return -ENOMEM;
+
+       fp = fopen(res->config_data.path_load_table, "r");
+       if (!fp)
+               return -EIO;
+
+       /* Read the title and drop the buffer because it is not used */
+       if (!fgets(str, BUFF_MAX, fp)) {
+               fclose(fp);
+               return -EIO;
+       }
+
+       for (i = 0; i < RESMON_SRC_CPUHP_COUNT; i++) {
+               ret = fscanf(fp, "%" SCNd64 "%u %u %u",
+                       &cpuhp_result[i].time,
+                       &cpuhp_result[i].freq,
+                       &cpuhp_result[i].freq_new,
+                       &cpuhp_result[i].nr_runnings);
+               if (ret < 0) {
+                       fclose(fp);
+                       return -EIO;
+               }
+
+               for (j = 0; j < res->config_data.num_cpus; j++) {
+                       ret = fscanf(fp, "%u", &cpuhp_result[i].load[j]);
+                       if (ret < 0) {
+                               fclose(fp);
+                               return -EIO;
+                       }
+               }
+       }
+
+       fclose(fp);
+
        return 0;
 }
 
index a046854a029e53cfdb5c56b347ea10a72528f773..52fdb4e1f325f8ba1cb7789a0261848e094c9009 100644 (file)
@@ -36,6 +36,9 @@ enum resmon_timer_type {
  *   CPU utilization/frequency/the number of running tasks. But this type
  *   is using nonstandard linux kernel interface. It should be replaced with
  *   the linux kernel standard interface.
+ *
+ * Description of result format of resource monitor's source type:
+ * - RESMON_SRC_CPUHP : struct resmon_result_src_cpuhp
  */
 enum resmon_src_type {
        RESMON_SRC_UNKNOWN              = 0x0,
@@ -43,6 +46,24 @@ enum resmon_src_type {
        RESMON_SRC_CPUHP                = 0x2,
 };
 
+/* Result of RESMON_SRC_CPUHP's resource monitor */
+struct resmon_result_src_cpuhp {
+       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;
+};
+
 /*
  * pass_resmon_register_timer - Register timer-based resource monitor.
  *