monitor算法是一种静态算法,超过阈值就限制为多少频率,或者做什么处理,ss不一样它是一种动态算法。
下面我们就从代码层面进行分析。也是在main函数中调用了ss_algo_init函数。
1. ss_algo_init
我们来看下这个函数的前半段函数,这里主要先是过滤配置中的setting,然后创建sensor的device的client,然后就是获取devie信息,还有就是将device的各个档位的信息lvl_info放入每个setting的lvl_arr中了。
int ss_algo_init(struct thermal_setting_t *setting)
{
int ret_val = 0;
struct device_info dev_info;
struct setting_info *cfg;
int err = 0;
uint8_t i = 0;
if (setting == NULL) {
msg("%s: Invalid Argument\n", __func__);
return -(EINVAL);
}
sem_init(&sem_config_set, 0, 1);
cfg = setting->list;
/* Import settings */
while (cfg) {
err = 0;
if (clnt_cnt >= MAX_INSTANCES_SUPPORTED) {//最大根数限制
msg("%s: Max SS instances reached.", __func__);
break;
}
if (cfg->algo_type != SS_ALGO_TYPE) {//类型过滤
cfg = cfg->next;
continue;
}
if (cfg->err_disable) {//错误过滤
info("%s: Entry Disabled %s.", __func__,
cfg->desc);
cfg = cfg->next;
continue;
}
if (cfg->data.ss.sampling_period_ms == 0) {//采样率没有配置
msg("%s: Sampling is not configured, "
"disabling entry %s", __func__, cfg->desc);
continue;
}
algo_clnt[clnt_cnt].sensor_clnt =//为每一个setting创建一个sensor的client
sensors_manager_reg_clnt(cfg->data.ss.sensor);
if (algo_clnt[clnt_cnt].sensor_clnt == NULL) {
msg("%s: Sensor clnt create fail %s\n", __func__,
cfg->data.ss.sensor);
err = EFAULT;
goto error_handler;
}
algo_clnt[clnt_cnt].dev_clnt =//为每个setting创建device的client,这里不像monitor算法,只有有一个device
devices_manager_reg_clnt(cfg->data.ss.device);
if (algo_clnt[clnt_cnt].dev_clnt == NULL) {
msg("%s: Device clnt create fail %s\n", __func__,
cfg->data.ss.device);
err = EFAULT;
goto error_handler;
}
err = devices_manager_get_info(cfg->data.ss.device,
&dev_info);//获取device的device_info
if (err) {
msg("%s: Can not grab dev info %s\n", __func__,
cfg->data.ss.device);
goto error_handler;
}
if (dev_info.dev_type != DEVICE_OP_VALUE_TYPE) {//类型只能是这种,比如cpu、gpu
msg("%s: Improper dev_type %d\n", __func__,
cfg->algo_type);
err = EFAULT;
goto error_handler;
}
if (dev_info.num_of_levels == 0) {//必须要有多档位,比如cpu、gpu
msg("%s: No levels supported for this device.\n",
__func__);
err = EFAULT;
goto error_handler;
}
algo_clnt[clnt_cnt].lvl_arr = (struct device_lvl_info *)
malloc(sizeof(struct device_lvl_info) *
dev_info.num_of_levels);
err = devices_manager_get_lvl_list(cfg->data.ss.device,
algo_clnt[clnt_cnt].lvl_arr,
&dev_info.num_of_levels);//把每个device的lvl_info传入每个setting的lvl_arr中
if (err) {
msg("%s: Can not grab dev lvl list %s\n", __func__,
cfg->data.ss.device);
goto error_handler;
}
我们再来看下这个函数的后半段代码,我们主要看没有出错的处理
error_handler:
if (err) {//出错的处理
/* Clean up and look for next SS cfg */
if (algo_clnt[clnt_cnt].sensor_clnt)
sensors_manager_dereg_clnt(
algo_clnt[clnt_cnt].sensor_clnt);
if (algo_clnt[clnt_cnt].dev_clnt)
devices_manager_dereg_clnt(
algo_clnt[clnt_cnt].dev_clnt);
if (algo_clnt[clnt_cnt].lvl_arr)
free(algo_clnt[clnt_cnt].lvl_arr);
memset(&algo_clnt[clnt_cnt], 0x0,
sizeof(struct ss_algo_t));
} else {
algo_clnt[clnt_cnt].disabled =
cfg->disable;
algo_clnt[clnt_cnt].state =
SS_STATE_STOP_ALGO;//初始的状态
algo_clnt[clnt_cnt].min_op_lvl =
dev_info.min_dev_op_value;//最新值
algo_clnt[clnt_cnt].max_op_lvl =
dev_info.max_dev_op_value;
algo_clnt[clnt_cnt].dev_op_lvl =
dev_info.max_dev_op_value;
algo_clnt[clnt_cnt].setting = &(cfg->data.ss);
algo_clnt[clnt_cnt].desc = cfg->desc;
algo_clnt[clnt_cnt].num_of_lvls =
dev_info.num_of_levels;
algo_clnt[clnt_cnt].active_set_point =//触发值
cfg->data.ss.set_point;
algo_clnt[clnt_cnt].active_set_point_clr =//清除值
cfg->data.ss.set_point_clr;
if (cfg->data.ss.device_mtgn_max_limit == 1)
algo_clnt[clnt_cnt].dev_mtgn_max_limit = 0;
else
algo_clnt[clnt_cnt].dev_mtgn_max_limit =
cfg->data.ss.device_mtgn_max_limit;
if (cfg->data.ss.device_perf_floor == 1)
algo_clnt[clnt_cnt].device_perf_floor = 0;
else
algo_clnt[clnt_cnt].device_perf_floor =
cfg->data.ss.device_perf_floor;
cfg->data.ss.sampling_period_ms =
MIN(SAMPLE_PERIOD,
cfg->data.ss.sampling_period_ms);
strlcpy(algo_clnt[clnt_cnt].device_units,
&dev_info.device_units_name[0], MAX_UNIT_NAME_SIZE);
dbgmsg("%s: SS ID %s, Sensor %s\n", __func__, cfg->desc,
cfg->data.ss.sensor);
dbgmsg("%s: Device %s, Number of Levels %d\n",
__func__, cfg->data.ss.device,
algo_clnt[clnt_cnt].num_of_lvls);
dbgmsg("%s: Set Point %dmC, Set Point Clr %dmC, "
"Override %dmC\n", __func__,
cfg->data.ss.set_point,
cfg->data.ss.set_point_clr,
cfg->data.ss.override);
dbgmsg("%s: MAXFREQ %dkHz, MINFREQ %dkHz, TC %d", __func__,
dev_info.max_dev_op_value,
dev_info.min_dev_op_value,
cfg->data.ss.time_constant);
if (!cfg->disable)
print_setting(cfg);
/* Create sampling groups for similarly configured
intervals and save sampling group id of each client
on its own algo info */
for (i = 0; i < MAX_INSTANCES_SUPPORTED &&
sampling_groups[i].sampling != 0; i++) {
if (cfg->data.ss.sampling_period_ms ==
sampling_groups[i].sampling) {
algo_clnt[clnt_cnt].sampling_group_id = i;
break;
}
}
if (i >= MAX_INSTANCES_SUPPORTED ||
(sampling_groups[i].sampling == 0 &&
sampling_group_count >= MAX_INSTANCES_SUPPORTED)) {
msg("%s: Sampling group count max is reached:%d idx:%d\n",
__func__, sampling_group_count, i);
err = -1;
goto error_handler;
} else if (sampling_groups[i].sampling == 0) {
sampling_groups[i].sampling =
cfg->data.ss.sampling_period_ms;//将每个setting下面的采样率放在sampling_groups数组中
algo_clnt[clnt_cnt].sampling_group_id = i;
sampling_group_count++;
}
clnt_cnt++;
}
cfg = cfg->next;
}
if (clnt_cnt == 0) {
info("%s: No SS's configured.\n", __func__);
return -(EFAULT);
}
ret_val = pthread_create(&thread, NULL, (void *)&algo_monitor,//创建线程执行algo_monitor算法监控
NULL);
if (ret_val != 0)
msg("Error initializing SS algo monitor\n");
return ret_val;
}
2. algo_monitor
下面我们来看下algo_monitor函数,这个函数主要是开启线程后去执行是ss算法的主函数。主要通过掩码去执行不同函数,并且函数也会等待condition,直到有condition broadcast之后,才会继续执行。
static void *algo_monitor(void *data)
{
uint32_t local_ev_mask &