#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;
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;
/*
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;
/*
- * 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
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)
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;
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;
}
}
-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");
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 {
_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;
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");
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;
}
/*
/* 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");
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)
static int cpuhp_governor_exit(struct pass_resource *res)
{
struct pass_cpuhp *cpuhp = &res->cpuhp;
- int i;
/*
* Stop timer and
*/
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);
cpuhp->pass_cpu_threshold = 0;
cpuhp->up_threshold = 0;
cpuhp->down_threshold = 0;
- cpuhp->num_pass_cpu_stats = 0;
cpuhp->governor = NULL;
return 0;
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)
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) {