既上一篇博客继续分析main函数,上一篇博客我们分析了devices_init device的初始化,这篇博客先是分析保持KTM工作,后面主要分析sensor的初始化,。
我们先来看如下,先是创建了一个kernel的client,然后因为有kernel 的device,所以会调用device_clnt_request函数
kernel_dev = devices_manager_reg_clnt("kernel");//创建一个kernel device的client
if (kernel_dev == NULL) {
msg("%s Failed to create kernel device handle\n", __func__);
} else {
req.value = 1;//有kernel device
device_clnt_request(kernel_dev, &req);
}
上一篇博客我们分析过device_clnt_reques函数,这里传进来的device的type不一样我们再来分析下。kernel的device的type是DEVICE_GENERIC_TYPE,所以调用了devices_manager_set_lvl函数
int device_clnt_request(device_clnt_handle clnt, union device_request *req)
{
struct devices_manager_dev *dev_mgr = NULL;
struct device_clnt *client = clnt;
int ret_val = 0;
if ((client == NULL) || (req == NULL)) {
msg("%s: Invalid args.\n", __func__);
return -(EINVAL);
}
ret_val = validate_clnt(client);//验证client,就是遍历device的list看每个device的client有没有这个client
if (ret_val != 0)
return ret_val;
dev_mgr = client->dev_mgr;
switch (dev_mgr->dev_info.dev_type) {
case DEVICE_GENERIC_TYPE://kernel的device的type为这个
ret_val = devices_manager_set_lvl(dev_mgr, client, req->value);
break;
case DEVICE_OP_VALUE_TYPE:
ret_val = devices_manager_set_op_value(dev_mgr, client,
req->value);
break;
case DEVICE_DIRECT_ACTION_TYPE:
ret_val = devices_manager_set_direct_action(dev_mgr, client,
req);
break;
default:
dbgmsg("%s: Unhandled dev_type %d", __func__,
dev_mgr->dev_info.dev_type);
break;
}
return ret_val;
}
devices_manager_set_lvl函数设置了client的request.value的值,然后调用了update_dev_state来更新device的state。
static int devices_manager_set_lvl(struct devices_manager_dev *dev_mgr,
struct device_clnt *client, int lvl)
{
lvl = MIN(lvl, (int)(dev_mgr->dev_info.num_of_levels - 1));
lvl = MAX(lvl, (int)(dev_mgr->dev_info.min_lvl));
pthread_mutex_lock(&clnt_mtx);
client->request.value = lvl;
client->request_active = 1;
pthread_mutex_unlock(&clnt_mtx);
dbgmsg("%s: DEV %s, lvl %d\n", __func__,
dev_mgr->dev_info.name, lvl);
update_dev_state(dev_mgr);
return dev_mgr->active_req.value;;
}
update_dev_state函数上一篇博客已经分析过了,这里我们再来看下这里主要是遍历所有的client找到其最大值然后调用device的action函数。
static int update_dev_state(struct devices_manager_dev *dev_mgr)
{
union device_request req;
struct device_clnt *client = dev_mgr->client_list;
if ((dev_mgr->dev_info.dev_type != DEVICE_GENERIC_TYPE) &&
(dev_mgr->dev_info.dev_type != DEVICE_OP_VALUE_TYPE))
return -(EFAULT);
pthread_mutex_lock(&clnt_mtx);
if (dev_mgr->dev_info.dev_type == DEVICE_GENERIC_TYPE) {//kernel的type为这个分支
/* Start from min level to find the highest existing client request */
req.value = dev_mgr->dev_info.min_lvl;//device的min_lvl作为初始值
/* Walk client list to find highest mitigation level */
while (client != NULL) {
if (client->request_active)
req.value = MAX(req.value, client->request.value);//遍历所有的client的req.value取其最大值
client = client->next_clnt;
}
} else if (dev_mgr->dev_info.dev_type == DEVICE_OP_VALUE_TYPE) {
/* Start from max allowable value find lowest request */
req.value = dev_mgr->dev_info.max_dev_op_value;
/* Walk client list to find highest mitigation level */
while (client != NULL) {
if (client->request_active)
req.value = MIN(req.value, client->request.value);
client = client->next_clnt;
}
}
if (dev_mgr->active_req.value != req.value) {
dev_mgr->active_req.value = req.value;
if (dev_mgr->action)
dev_mgr->action(dev_mgr);//调用device的action函数
/* Notify clients */
client = dev_mgr->client_list;
while (client != NULL) {//如果client有回调,就调用回调
if (client->cb_func != NULL)
client->cb_func(client, &req,
client->cb_usr_data);
client = client->next_clnt;
}
}
pthread_mutex_unlock(&clnt_mtx);
return 0;
}
而kernel的action最后调用了kernel_mitigation_request函数
static int kernel_mitigation_action(struct devices_manager_dev *dev_mgr)
{
return kernel_mitigation_request(dev_mgr->active_req.value);
}
kernel_mitigation_request函数现在的request传入的是1,因此不做操作就是继续保持kernel的KTM工作,而当我们的thermal-engine完全工作后(初始化完成),最后会重新走到这,那时request为0,就会write /sys/module/msm_thermal/parameters/enabled节点为N,接管KTM的工作, 当KTM停止工作时,之前在thermal驱动设置的频率会重置。
int kernel_mitigation_request(int request)
{
int ret = -1;
pthread_mutex_lock(&kernel_disable_mtx);
if (request == 0) {
/* Disable kernel thermal module and take over */
write_to_file("/sys/module/msm_thermal/parameters/enabled",
"N" , strlen("N") + 1);
dbgmsg("KERNEL mitigation disabled\n");
} else
dbgmsg("KERNEL request to keep mitigation enabled\n");
pthread_mutex_unlock(&kernel_disable_mtx);
return ret;
}
这节我们开始分析sensor的初始化,main函数调用了sensors_init函数,这个minimum_mode一般为0,我们的代码在Sensors.c中,这个可以从Android.mk查看。
int sensors_init(int minimum_mode)
{
int ret_val = 0;
min_mode = minimum_mode;
if (!min_mode)
modem_ts_qmi_init();//这里和modem通信的qmi我们后续分析
init_sensor_alias();
parse_thermal_zones();
/* BCL */
if (add_tgt_sensors_set(bcl_sensors,
ARRAY_SIZE(bcl_sensors)) != 0) {
msg("%s: Error adding BCL TS\n", __func__);
ret_val = -(EFAULT);
}
return ret_val;
}
2.1 读取每个sensor的信息
我们来看下init_sensor_alias函数,先从节点/sys/module/msm_thermal/sensor_info读取节点信息,然后保存sensor信息到sensors数组中,这个sensors的类型是msm_sensor_info。
static void init_sensor_alias(void)
{
char buf[MAX_SENSOR_INFO_LEN];
char *psensor_info = NULL, *psave1 = NULL;
if (read_line_from_file(SENSOR_INFO_SYSFS, buf,//读取/sys/module/msm_thermal/sensor_info节点信息
MAX_SENSOR_INFO_LEN) <= 0)
return;
psensor_info = strtok_r(buf, " ", &psave1);
while (psensor_info != NULL && sensor_cnt < MAX_NUM_SENSORS) {
char *psensor = NULL;
char *psave2 = NULL;
psensor = strtok_r(psensor_info, ":", &psave2);
if ((psensor == NULL) || strlcpy(sensors[sensor_cnt].type,//type
psensor, MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
goto next_sensor;
psensor = strtok_r(NULL, ":", &psave2);
if ((psensor == NULL) || strlcpy(sensors[sensor_cnt].name,//name
psensor, MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
goto next_sensor;
if (psensor[strlen(psensor) + 1] != ':') {
psensor = strtok_r(NULL, ":", &psave2);
if ((psensor == NULL) ||
strlcpy(sensors[sensor_cnt].alias, psensor,//alias
MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
goto next_sensor;
}
psensor = strtok_r(NULL, ":", &psave2);
if (psensor == NULL)
goto next_sensor;
sensors[sensor_cnt].scaling_factor =
(int)strtol( psensor, NULL, 10);
if (sensors[sensor_cnt].scaling_factor <= 0)//scaling_factor
sensors[sensor_cnt].scaling_factor = 1;
sensor_cnt++;
next_sensor:
psensor_info = strtok_r(NULL, " ", &psave1);
}
dbgmsg("%s: sensor_cnt:%d\n", __func__, sensor_cnt);
}
我们来先看下节点/sys/module/msm_thermal/sensor_info节点读取到的信息。以冒号为分割第一个是sensor的type,第二个是sensor的name,第三个是alias,第四个是scaling_factor。
tsens:tsens_tz_sensor0:pop_mem:1 tsens:tsens_tz_sensor1::1 tsens:tsens_tz_sensor2::1 tsens:tsens_tz_sensor3:cpu0-cpu2:1 tsens:tsens_tz_sensor4:cpu1-cpu3:1 adc:pa_therm0::1 adc:case_therm::1 alarm:pm8909_tz::1000 adc:xo_therm::1 adc:xo_therm_buf::1
2.2 创建sensor
创建sensor有两种方法,一种读取sys/devices/vitual/thermal下的设备创建,另一种可以直接做一个sensor_info的数组,直接遍历数组创建sensor。
2.2.1 读取thermal节点创建sensor
再来看看parse_thermal_zones函数,这个函数主要看/sys/devices/virtual/thermal下面每个目录下的type 是否和我们前面保存的sensors数组中的sensor的name一样,不一样我们直接跳过。一样的话,我们在根据这个sensor的type调用不同的函数。
static void parse_thermal_zones(void)
{
DIR *tdir = NULL;
struct dirent *tdirent = NULL;
char name[MAX_PATH] = {0};
char cwd[MAX_PATH] = {0};
int cnt = 0, ret = 0;
if (!getcwd(cwd, sizeof(cwd)))
return;
if (sensor_cnt <= 0)
return init_user_space_sensors();
ret = chdir(THERMAL_SYSFS); /* Change dir to read the entries. Doesnt work
otherwise */
tdir = opendir(THERMAL_SYSFS);//sys/devices/virtual/thermal目录
if (!tdir || ret) {
msg("%s: Unable to open %s\n", __func__, THERMAL_SYSFS);
return;
}
while ((tdirent = readdir(tdir))) {
char buf[MAX_PATH];
DIR *tzdir = NULL;
tzdir = opendir(tdirent->d_name);
if (!tzdir)
continue;
snprintf(name, MAX_PATH, SENSOR_TZ_TYPE, tdirent->d_name);//sys/devices/virtual/thermal目录下个各个子目录下的type值
dbgmsg("%s: Opening %s\n", __func__, name);
ret = read_line_from_file(name, buf, sizeof(buf));
if (ret <= 0)
continue;
buf[strlen(buf) -1] = '\0';
for (cnt = 0; cnt < sensor_cnt; cnt++) {
if (strncmp(buf, sensors[cnt].name,//每一个type值和sensors数组中sensor的那么做对比,不同直接continue
MAX_SENSOR_NAME_LEN))
continue;
if (!strncmp(sensors[cnt].type, TSENS_TYPE,//类型不同调用不同的函数
strlen(TSENS_TYPE))
|| !strncmp(sensors[cnt].type, LLM_TYPE,
strlen(LLM_TYPE))) {
add_tgt_tsens_sensors(sensors[cnt].name, &sensors[cnt]);
dbgmsg(
"%s: Added sensor: %s to %s sensor list\n",
__func__, buf, sensors[cnt].type);
} else if (!strncmp(sensors[cnt].type, ALARM_TYPE,
strlen(ALARM_TYPE)) ||
(!strncmp(sensors[cnt].type, ADC_TYPE,
strlen(ADC_TYPE)))) {
add_tgt_gen_sensors(sensors[cnt].name,
&sensors[cnt]);
dbgmsg(
"%s: Added sensor: %s to %s sensor list\n",
__func__, buf, sensors[cnt].type);
}
}
closedir(tzdir);
}
closedir(tdir);
ret = chdir(cwd); /* Restore current working dir */
}
我们先来看下sys/devices/virtual/thermal目录下的各个目录
然后再来看各个目录下type的值。
我们接着看上面根据sensor的type不同调用了不同的函数。 如果是tsens和llm的type调用add_tgt_tsens_sensors函数
static int add_tgt_tsens_sensors(char *sensor_name, struct msm_sensor_info *sens_info)
{
int ret_val = 0;
struct sensor_info *sensor;
sensor = malloc(sizeof(struct sensor_info));//创建sensor
if (sensor == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor, 0, sizeof(struct sensor_info));
sensor->name = malloc(MAX_SENSOR_NAME_LEN);
if (sensor->name == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor->name, 0, MAX_SENSOR_NAME_LEN);
strlcpy(sensor->name, sensor_name, MAX_SENSOR_NAME_LEN);
sensor->setup = tsens_sensors_setup;//获取到sensor的fd,就是各个zone下面的temp文件
sensor->shutdown = tsens_sensors_shutdown;//close fd
sensor->get_temperature = tsens_sensor_get_temperature;//获取温度的方法,从fd读取
sensor->get_trip_temperature = NULL;
sensor->interrupt_wait = tsens_sensor_interrupt_wait;
sensor->update_thresholds = tsens_sensor_update_thresholds;
sensor->tzn = 0;
sensor->data = NULL;
sensor->interrupt_enable = 1;
sensor->scaling_factor = sens_info->scaling_factor;
pthread_mutex_init(&(sensor->read_mtx), NULL);
add_tgt_sensor(sensor);//新建一个sensors_mgr_sensor_info对象
error_handler:
if (ret_val) {
if (sensor) {
if (sensor->name)
free(sensor->name);
free(sensor);
}
}
return ret_val;
}
add_tgt_sensor函数就是新建一个sensors_mgr_sensor_info对象,并且将sensor_info中的name alias,方法都复制过来。
static int add_tgt_sensor(struct sensor_info *sensor)
{
int ret_val = 0;
struct sensors_mgr_sensor_info *sensor_mgr = NULL;
dbgmsg("%s: Add sensor:%s to sensor list\n", __func__, sensor->name);
sensor_mgr = malloc(sizeof(struct sensors_mgr_sensor_info));
if (sensor_mgr == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor_mgr, 0, sizeof(struct sensors_mgr_sensor_info));
sensor_mgr->name = sensor->name;
sensor_mgr->alias = find_alias(sensor->name);
if (sensor->setup(sensor) == 0) {//会在这里调用sensor中的setup获取sensor的fd
msg("%s: %s sensor setup failed failed.\n",
__func__, sensor->name);
ret_val = -(EFAULT);
goto error_handler;
}
sensor_mgr->data = (void*) sensor;
sensor->sensor_mgr = sensor_mgr;
sensor_mgr->get_temperature = generic_read;
sensor_mgr->shutdown = generic_shutdown;
if (sensor->interrupt_wait)
sensor_mgr->wait = generic_wait;
if (sensor->update_thresholds)
sensor_mgr->update_thresholds = generic_update_thresholds;
if (sensor->get_trip_temperature)
sensor_mgr->get_trip_temperature = generic_trip_temp_read;
sensors_manager_add_sensor(sensor_mgr);//将这个sensor放入sensor_list中
error_handler:
if (ret_val) {
if (sensor_mgr)
free(sensor_mgr);
}
return ret_val;
}
如果是sensor的type是alarm和adc的话调用add_tgt_gen_sensors函数,这个函数和上面的函数类似,最后也是调用add_tgt_sensor函数创建sensors_mgr_sensor_info对象最后加入sensor_list中
static int add_tgt_gen_sensors(char *sensor_name, struct msm_sensor_info *sens_info)
{
int ret_val = 0;
struct sensor_info *sensor;
sensor = malloc(sizeof(struct sensor_info));
if (sensor == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor, 0, sizeof(struct sensor_info));
sensor->name = malloc(MAX_SENSOR_NAME_LEN);
if (sensor->name == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor->name, 0, MAX_SENSOR_NAME_LEN);
strlcpy(sensor->name, sensor_name, MAX_SENSOR_NAME_LEN);
sensor->setup = thermal_sensor_setup;
sensor->shutdown = thermal_sensor_shutdown;
sensor->get_temperature = thermal_sensor_get_temperature;
sensor->get_trip_temperature = NULL;
sensor->update_thresholds = NULL;
sensor->scaling_factor = sens_info->scaling_factor;
if (!strncmp(sens_info->type, ALARM_TYPE, strlen(ALARM_TYPE))) {
sensor->interrupt_enable = 1;
sensor->interrupt_wait = thermal_sensor_interrupt_wait;
} else if (!strncmp(sens_info->type, USERSPACE_TYPE,
strlen(USERSPACE_TYPE))) {
sensor->interrupt_enable = 1;
sensor->interrupt_wait = thermal_sensor_interrupt_wait;
sensor->update_thresholds = thermal_sensor_update_thresholds;
sensor->get_trip_temperature = thermal_sensor_get_trip_temp;
sensor->scaling_factor = 1000;
} else {
sensor->interrupt_enable = 0;
sensor->interrupt_wait = NULL;
}
pthread_mutex_init(&(sensor->read_mtx), NULL);
sensor->tzn = 0;
sensor->data = NULL;
add_tgt_sensor(sensor);
error_handler:
if (ret_val) {
if (sensor) {
if (sensor->name)
free(sensor->name);
free(sensor);
}
}
return ret_val;
}
我们再来重新看下add_tgt_sensor函数,注意我们传进来的参数sensor类型是sensor_info,而这里我们新建的sensor_mgr是sensors_mgr_sensor_info
static int add_tgt_sensor(struct sensor_info *sensor)
{
int ret_val = 0;
struct sensors_mgr_sensor_info *sensor_mgr = NULL;
dbgmsg("%s: Add sensor:%s to sensor list\n", __func__, sensor->name);
sensor_mgr = malloc(sizeof(struct sensors_mgr_sensor_info));
if (sensor_mgr == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor_mgr, 0, sizeof(struct sensors_mgr_sensor_info));
sensor_mgr->name = sensor->name;//name直接使用
sensor_mgr->alias = find_alias(sensor->name);//从sensors数组中找
if (sensor->setup(sensor) == 0) {//调用sensor的setup函数
msg("%s: %s sensor setup failed failed.\n",
__func__, sensor->name);
ret_val = -(EFAULT);
goto error_handler;
}
sensor_mgr->data = (void*) sensor;//将sensor放入sensor_mgr的data
sensor->sensor_mgr = sensor_mgr;
sensor_mgr->get_temperature = generic_read;//sensor_mgr的函数都是最后通过其data(sensor的各个函数执行)
sensor_mgr->shutdown = generic_shutdown;
if (sensor->interrupt_wait)
sensor_mgr->wait = generic_wait;
if (sensor->update_thresholds)
sensor_mgr->update_thresholds = generic_update_thresholds;
if (sensor->get_trip_temperature)
sensor_mgr->get_trip_temperature = generic_trip_temp_read;
sensors_manager_add_sensor(sensor_mgr);
error_handler:
if (ret_val) {
if (sensor_mgr)
free(sensor_mgr);
}
return ret_val;
}
我们举个读取温度的为例,最终就是通过sensor_mgr的data,就是sensor的get_temperature函数执行。
static int generic_read(struct sensors_mgr_sensor_info *sensor_mgr)
{
struct sensor_info *sensor = (struct sensor_info *)sensor_mgr->data;
return sensor->get_temperature(sensor);
}
我们再来看sensors_manager_add_sensor函数,将sensor_mgr放入sensor_list列表中。然后创建了一个线程执行sensor_monitor函数,sensor_mgr作为参数传入sensor_monitor函数。
int sensors_manager_add_sensor(struct sensors_mgr_sensor_info *sensor_mgr)
{
if (sensor_mgr == NULL) {
msg("%s: Invalid argument\n", __func__);
return -(EINVAL);
}
dbgmsg("%s: add sensor %s\n", __func__, sensor_mgr->name);
if (!sensor_mgr->default_polling_interval)
sensor_mgr->default_polling_interval = SENSOR_DEFAULT_POLLING_INTERVAL;
/* Just add new device to begining of list */
sensor_mgr->next_sensor = sensor_list;
sensor_list = sensor_mgr;
sensor_cnt++;
if (sensor_mgr->alias)
alias_cnt++;
pthread_mutex_init(&(sensor_mgr->req_wait_mutex), NULL);
pthread_cond_init(&(sensor_mgr->req_wait_cond), NULL);
pthread_create(&(sensor_mgr->monitor_thread), NULL,
sensor_monitor, sensor_mgr);
return 0;
}
2.2.2 sensor监控函数
下面我们就来看下sensor_monitor函数,这个函数在没创建一个sensor最后放入sensor_list的时候开启一个线程对该sensor进行监控。
static void *sensor_monitor(void *vsensor_mgr)
{
struct sensors_mgr_sensor_info *sensor_mgr = vsensor_mgr;
while (sensor_mgr->thread_shutdown != 1) {//这个只有在sensor被remove的时候才会退出
/* Wait here until there is actually a request to process */
if (!sensor_mgr->req_active) {
dbgmsg("%s: %s Wait for client request.\n", __func__, sensor_mgr->name);
pthread_mutex_lock(&(sensor_mgr->req_wait_mutex));
while (!sensor_mgr->req_active) {//只有当sensor_mgr的req_active为1该线程才会继续
pthread_cond_wait(&(sensor_mgr->req_wait_cond),
&(sensor_mgr->req_wait_mutex));
}
pthread_mutex_unlock(&(sensor_mgr->req_wait_mutex));
}
dbgmsg("%s: %s Sensor wait.\n", __func__, sensor_mgr->name);
sensor_wait(sensor_mgr);//线程等待相关
if (sensor_mgr->get_trip_temperature)
sensor_mgr->last_reading =
sensor_mgr->get_trip_temperature(sensor_mgr);
else
sensor_mgr->last_reading =//获取温度保存在last_reading中
sensor_mgr->get_temperature(sensor_mgr);
dbgmsg("%s: %s Reading %d .\n", __func__, sensor_mgr->name,
sensor_mgr->last_reading);
.......//log
notify_clnts(sensor_mgr);//调用notify_clnts通知各个client
}
return NULL;
}
我们先来看下sensor_wait就是
static void sensor_wait(struct sensors_mgr_sensor_info *sensor_mgr)
{
if (sensor_mgr->wait)
sensor_mgr->wait(sensor_mgr);
else {
uint32_t polling_interval =
(sensor_mgr->active_thresh.polling_interval_valid)?
(sensor_mgr->active_thresh.polling_interval):
(sensor_mgr->default_polling_interval);
dbgmsg("%s: %s Wait start. %dms\n", __func__, sensor_mgr->name, polling_interval);
usleep(polling_interval*1000);
dbgmsg("%s: %s Wait done.\n", __func__, sensor_mgr->name);
}
}
每一个sensor_mgr的wait函数,最后都是调用的sensor_info的interrupt_wait函数,我们来看下如下的,都是利用condition来等待。
void thermal_sensor_interrupt_wait(struct sensor_info *sensor)
{
struct thermal_sensor_data *sensor_data;
if (NULL == sensor ||
NULL == sensor->data) {
msg("%s: unexpected NULL", __func__);
return;
}
sensor_data = (struct thermal_sensor_data *) sensor->data;
if (sensor->interrupt_enable) {
/* Wait for sensor threshold condition */
pthread_mutex_lock(&(sensor_data->thermal_sensor_mutex));
while (!sensor_data->threshold_reached) {
pthread_cond_wait(&(sensor_data->thermal_sensor_condition),
&(sensor_data->thermal_sensor_mutex));
}
sensor_data->threshold_reached = 0;
pthread_mutex_unlock(&(sensor_data->thermal_sensor_mutex));
}
}
我们再来看下notify_clnts函数,先是遍历了client的request.thresh然后调用回调,后面还调用了update_active_thresh函数最后会调用sensor_info的update_thresholds,我们后续再分析。
static int notify_clnts(struct sensors_mgr_sensor_info *sensor_mgr)
{
struct sensor_client_type *client = NULL;
enum sensor_notify_event_type thresh_event;
if (sensor_mgr == NULL)
return -(EINVAL);
client = sensor_mgr->client_list;
THERM_MUTEX_LOCK(&ts_clnt_mtx);
while (client != NULL) {
if (client->request_active) {
struct thresholds_req_t *thresh = &client->request.thresh;//遍历client的request.thresh
/* Notify clients of thresh crossings */
thresh_event = SENSOR_NOTIFY_NORMAL_THRESH_EVENT;
if (thresh->high_valid &&
(sensor_mgr->last_reading >= thresh->high)) {
thresh_event = SENSOR_NOTIFY_HIGH_THRESH_EVENT;
} else if (thresh->low_valid &&
(sensor_mgr->last_reading <= thresh->low)) {
thresh_event = SENSOR_NOTIFY_LOW_THRESH_EVENT;
}
if (thresh_event != SENSOR_NOTIFY_NORMAL_THRESH_EVENT) {
client->request_active = 0;
client->request.notify_cb_func(client,//调用request的回调函数
thresh_event,
sensor_mgr->last_reading,
client->request.notify_cb_data);
}
}
client = client->next_clnt;
}
THERM_MUTEX_UNLOCK(&ts_clnt_mtx);
update_active_thresh(sensor_mgr);
return 0;
}
2.2.3 读取sensor_info数组创建sensor
最后我们再来看看,bcl sensor的创建。这里和前面alarm adc tsens类型的sensor创建不一样,前面我们通过读取节点信息等等一步步最后得到sensor_info后再调用的add_tgt_sensor函数创建最后色sensor。这里直接调用了add_tgt_sensors_set函数。
int sensors_init(int minimum_mode)
{
......
/* BCL */
if (add_tgt_sensors_set(bcl_sensors,
ARRAY_SIZE(bcl_sensors)) != 0) {
msg("%s: Error adding BCL TS\n", __func__);
ret_val = -(EFAULT);
}
return ret_val;
}
我们来看下add_tgt_sensors_set函数,这里就是遍历传进来的bcl_sensors的list,这个已经是sensor_info类型的数组了,然后我们遍历这个数组,依次调用add_tgt_sensor创建sensor。
int add_tgt_sensors_set(struct sensor_info *sensor_arr, int arr_size)
{
int idx = 0;
int ret_val = 0;
for (idx = 0; idx < arr_size; idx++) {
if (add_tgt_sensor(&sensor_arr[idx]) != 0) {
msg("%s: Error adding %s\n", __func__,
sensor_arr[idx].name);
ret_val = -(EFAULT);
break;
}
}
return ret_val;
}
我们来看下bcl_sensors数组,目前只有一个sensor,就是sensor_info的结构体。
static struct sensor_info bcl_sensors[] = {
{
.name = "bcl",
.setup = bcl_setup,
.shutdown = bcl_shutdown,
.get_temperature = bcl_get_iavail,
.interrupt_wait = bcl_interrupt_wait,
.update_thresholds = bcl_update_thresholds,
.tzn = 0,
.data = NULL,
.get_trip_temperature = NULL,
.interrupt_enable = 1,
}
};
这样sensor的各个函数都分析了,下面我们从sensor监控温度的流程上进一步分析。
上面我们只是分析了一些函数,没有从流程上分析sensor是如何监控温度以及和各个算法联系起来的。
之前分析过add_tgt_tsens_sensors函数,这个函数的sensor主要是监控cpu、gpu的温度。我们再来看下这个函数。在add_tgt_sensor函数中我们会调用每个sensor的setup方法,每个sensor的setup方法我们要注意,然后我么还需要注意tsens_sensor_interrupt_wait和tsens_sensor_update_thresholds函数。
static int add_tgt_tsens_sensors(char *sensor_name, struct msm_sensor_info *sens_info)
{
int ret_val = 0;
struct sensor_info *sensor;
sensor = malloc(sizeof(struct sensor_info));
if (sensor == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor, 0, sizeof(struct sensor_info));
sensor->name = malloc(MAX_SENSOR_NAME_LEN);
if (sensor->name == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor->name, 0, MAX_SENSOR_NAME_LEN);
strlcpy(sensor->name, sensor_name, MAX_SENSOR_NAME_LEN);
sensor->setup = tsens_sensors_setup;
sensor->shutdown = tsens_sensors_shutdown;
sensor->get_temperature = tsens_sensor_get_temperature;
sensor->get_trip_temperature = NULL;
sensor->interrupt_wait = tsens_sensor_interrupt_wait;//有自己的wait函数
sensor->update_thresholds = tsens_sensor_update_thresholds;//更新sensor的thresholds的low和high
sensor->tzn = 0;
sensor->data = NULL;
sensor->interrupt_enable = 1;//允许中断
sensor->scaling_factor = sens_info->scaling_factor;
pthread_mutex_init(&(sensor->read_mtx), NULL);
add_tgt_sensor(sensor);
error_handler:
if (ret_val) {
if (sensor) {
if (sensor->name)
free(sensor->name);
free(sensor);
}
}
return ret_val;
}
我们先来看下sensor_monitor函数,先需要sensor的req_active为1,代表这个时候sensor的client有申请(这个在后面的算法会提到),这个时候我们再调用sensor_wait,这个函数会去等待
static void *sensor_monitor(void *vsensor_mgr)
{
struct sensors_mgr_sensor_info *sensor_mgr = vsensor_mgr;
while (sensor_mgr->thread_shutdown != 1) {
/* Wait here until there is actually a request to process */
if (!sensor_mgr->req_active) {
dbgmsg("%s: %s Wait for client request.\n", __func__, sensor_mgr->name);
pthread_mutex_lock(&(sensor_mgr->req_wait_mutex));
while (!sensor_mgr->req_active) {
pthread_cond_wait(&(sensor_mgr->req_wait_cond),
&(sensor_mgr->req_wait_mutex));
}
pthread_mutex_unlock(&(sensor_mgr->req_wait_mutex));
}
dbgmsg("%s: %s Sensor wait.\n", __func__, sensor_mgr->name);
sensor_wait(sensor_mgr);
if (sensor_mgr->get_trip_temperature)
sensor_mgr->last_reading =
sensor_mgr->get_trip_temperature(sensor_mgr);
else
sensor_mgr->last_reading =
sensor_mgr->get_temperature(sensor_mgr);
dbgmsg("%s: %s Reading %d .\n", __func__, sensor_mgr->name,
sensor_mgr->last_reading);
if (!strncmp(sensor_mgr->name, "bcl", 3)) {
thermalmsg(LOG_LVL_DBG, (LOG_LOGCAT | LOG_LOCAL_SOCKET),
"%s:%s:%d mA\n", SENSORS,
sensor_mgr->name, sensor_mgr->last_reading);
} else if (!strncmp(sensor_mgr->name, "bcm", 3)) {
thermalmsg(LOG_LVL_DBG, (LOG_LOGCAT | LOG_LOCAL_SOCKET),
"%s:%s:%d mPercent\n", SENSORS,
sensor_mgr->name, sensor_mgr->last_reading);
} else {
thermalmsg(LOG_LVL_DBG, (LOG_LOGCAT | LOG_LOCAL_SOCKET),
"%s:%s:%d mC\n", SENSORS,
sensor_mgr->name, sensor_mgr->last_reading);
}
notify_clnts(sensor_mgr);
}
return NULL;
}
我们来看这个sensor_wait函数,sensor有wait函数就去调用wait函数。没有就用usleep来替代,这个时候polling_interval就是每个配置算法中的采样率。
static void sensor_wait(struct sensors_mgr_sensor_info *sensor_mgr)
{
if (sensor_mgr->wait)
sensor_mgr->wait(sensor_mgr);
else {
uint32_t polling_interval =
(sensor_mgr->active_thresh.polling_interval_valid)?
(sensor_mgr->active_thresh.polling_interval):
(sensor_mgr->default_polling_interval);
dbgmsg("%s: %s Wait start. %dms\n", __func__, sensor_mgr->name, polling_interval);
usleep(polling_interval*1000);
dbgmsg("%s: %s Wait done.\n", __func__, sensor_mgr->name);
}
}
我们再来看上面的sensor的wait函数,这个函数先看这个sensor是否允许中断,如果允许然后一直等待condition,直到某个地方broadcast这个condition。下一步我们就要看哪个地方broadcast这个condition。
void tsens_sensor_interrupt_wait(struct sensor_info *sensor)
{
struct tsens_data *tsens;
if (NULL == sensor ||
NULL == sensor->data) {
msg("%s: unexpected NULL", __func__);
return;
}
if (sensor->interrupt_enable) {
tsens = (struct tsens_data *) sensor->data;
/* Wait for sensor threshold condition */
pthread_mutex_lock(&(tsens->tsens_mutex));
while (!tsens->threshold_reached) {
pthread_cond_wait(&(tsens->tsens_condition),
&(tsens->tsens_mutex));
}
tsens->threshold_reached = 0;
pthread_mutex_unlock(&(tsens->tsens_mutex));
}
}
我们来看前面的tsens_sensors_setup函数,最后会建一个thread来执行tsens_uevent函数。
int tsens_sensors_setup(struct sensor_info *sensor)
{
int fd = -1;
int sensor_count = 0;
char name[MAX_PATH] = {0};
int tzn = 0;
struct tsens_data *tsens = NULL;
tzn = get_tzn(sensor->name);
if (tzn < 0) {
msg("No thermal zone device found in the kernel for sensor %s\n", sensor->name);
return sensor_count;
}
sensor->tzn = tzn;
snprintf(name, MAX_PATH, TZ_TEMP, sensor->tzn);
fd = open(name, O_RDONLY);
if (fd < 0) {
msg("%s: Error opening %s\n", __func__, TZ_TEMP);
return sensor_count;
}
/* Allocate TSENS data */
tsens = (struct tsens_data *) malloc(sizeof(struct tsens_data));
if (NULL == tsens) {
msg("%s: malloc failed", __func__);
close(fd);
return sensor_count;
}
memset(tsens, 0, sizeof(struct tsens_data));
sensor->data = (void *) tsens;
sensor_count++;
pthread_mutex_init(&(tsens->tsens_mutex), NULL);
pthread_cond_init(&(tsens->tsens_condition), NULL);
tsens->sensor_shutdown = 0;
tsens->threshold_reached = 0;
tsens->sensor = sensor;
sensor->fd = fd;
init_tsens_trip_type(tsens);
if (sensor->interrupt_enable) {
pthread_create(&(tsens->tsens_thread), NULL,
tsens_uevent, sensor);
}
return sensor_count;
}
我们来分析下这个函数,这个函数就是去读每个sensor的/sys/devices/virtual/thermal/thermal_zone%d/type节点了,然后使用poll,看看是否有事件可以读取,然后再去将上面提到的condition去broadcast,这样sensor_wait的等待就结束了。那么这个节点什么时候会有事件呢,稍后我们会提到一个update threshold这个,这个最后就是往sensor驱动下一个threshold的low和high,只要sensor驱动读取的数据大于high或者小于low,就会触发/sys/devices/virtual/thermal/thermal_zone%d/type节点了,就会有数据上来,这个时候sensor_wait就结束等待了。
static void *tsens_uevent(void *data)
{
int err = 0;
struct sensor_info *sensor = (struct sensor_info *)data;
struct pollfd fds;
int fd;
char uevent[MAX_PATH] = {0};
char buf[MAX_PATH] = {0};
struct tsens_data *tsens = NULL;
if (NULL == sensor ||
NULL == sensor->data) {
msg("%s: unexpected NULL", __func__);
return NULL;
}
tsens = (struct tsens_data *) sensor->data;
/* Looking for tsens uevent */
snprintf(uevent, MAX_PATH, TZ_TYPE, sensor->tzn);
fd = open(uevent, O_RDONLY);
if (fd < 0) {
msg("Unable to open %s to receive notifications.\n", uevent);
return NULL;
};
while (!tsens->sensor_shutdown) {
fds.fd = fd;
fds.events = POLLERR|POLLPRI;
fds.revents = 0;
err = poll(&fds, 1, -1);
if (err == -1) {
msg("Error in uevent poll.\n");
break;
}
err = read(fd, buf, sizeof(buf));
if (err < 0)
msg("sysfs[%s] read error:%d\n", uevent, errno);
lseek(fd, 0, SEEK_SET);
dbgmsg("%s: %s", __func__, buf);
/* notify the waiting threads */
pthread_mutex_lock(&(tsens->tsens_mutex));
tsens->threshold_reached = 1;//sensor的threshold被触发
pthread_cond_broadcast(&(tsens->tsens_condition));//broadcast condition
pthread_mutex_unlock(&(tsens->tsens_mutex));
}
close(fd);
return NULL;
}
我们再来看函数,就会去遍历每一个client,如果当前的温度超过了该client thresh的high或者low就会调用该client的回调(其实就去处理该配置算法的流程了),最后还会调用update_active_thresh函数来更新sensor的thresh值。
static int notify_clnts(struct sensors_mgr_sensor_info *sensor_mgr)
{
struct sensor_client_type *client = NULL;
enum sensor_notify_event_type thresh_event;
if (sensor_mgr == NULL)
return -(EINVAL);
client = sensor_mgr->client_list;
THERM_MUTEX_LOCK(&ts_clnt_mtx);
while (client != NULL) {
if (client->request_active) {
struct thresholds_req_t *thresh = &client->request.thresh;
/* Notify clients of thresh crossings */
thresh_event = SENSOR_NOTIFY_NORMAL_THRESH_EVENT;
if (thresh->high_valid &&
(sensor_mgr->last_reading >= thresh->high)) {
thresh_event = SENSOR_NOTIFY_HIGH_THRESH_EVENT;
} else if (thresh->low_valid &&
(sensor_mgr->last_reading <= thresh->low)) {
thresh_event = SENSOR_NOTIFY_LOW_THRESH_EVENT;
}
if (thresh_event != SENSOR_NOTIFY_NORMAL_THRESH_EVENT) {
client->request_active = 0;
client->request.notify_cb_func(client,//调用各个client的回调
thresh_event,
sensor_mgr->last_reading,
client->request.notify_cb_data);
}
}
client = client->next_clnt;
}
THERM_MUTEX_UNLOCK(&ts_clnt_mtx);
update_active_thresh(sensor_mgr);
return 0;
}
我们来看下update_active_thresh函数,其实就是遍历各个client获取thresh.high thresh.low然后比较保存在sensor中,然后调用sensor的update_thresholds函数。这函数在各个算法初始化的时候都会去调用,用来设置各个client thresh的low、high然后设置到sensor中(比如ss算法中会去调用sensors_manager_set_thresh_lvl函数设置client的thresh,最后还是调用update_active_thresh函数来更新sensor中的值)
static int update_active_thresh(struct sensors_mgr_sensor_info *sensor_mgr)
{
struct sensor_client_type *client = NULL;
struct sensor_thresh_req *active = NULL;
uint8_t active_req = 0;
if (sensor_mgr == NULL)
return -(EINVAL);
active = &sensor_mgr->active_thresh;
memset(active, 0, sizeof(struct sensor_thresh_req));
active->thresh.low = INT32_MIN;
active->thresh.high = INT32_MAX;
active->polling_interval = UINT32_MAX;
client = sensor_mgr->client_list;
THERM_MUTEX_LOCK(&ts_clnt_mtx);
while (client != NULL) {
if (!client->request_active) {
client = client->next_clnt;
continue;
}
struct sensor_thresh_req *thresh = &client->request;
if (thresh->thresh.descending_threshold)
active->thresh.descending_threshold = 1;
/* Find active high */
if (thresh->thresh.high_valid) {
active->thresh.high_valid = 1;
active->thresh.high = MIN(active->thresh.high,
thresh->thresh.high);
}
/* Find active low */
if (thresh->thresh.low_valid) {
active->thresh.low_valid = 1;
active->thresh.low = MAX(active->thresh.low,
thresh->thresh.low);
}
/* Find min polling interval */
if (thresh->polling_interval_valid) {
active->polling_interval_valid = 1;
active->polling_interval = MIN(active->polling_interval,
thresh->polling_interval);
}
active_req = 1;
client = client->next_clnt;
}
if ((active->thresh.high > active->thresh.low) &&//当high大于low 并且high_valid或者low_valid才需要更新sensor的threshold
(active->thresh.high_valid || active->thresh.low_valid)) {
/* We can take advantage of interrupt */
sensor_mgr->active_thresh_valid = 1;
} else {
sensor_mgr->active_thresh_valid = 0;
}
/* Room for optimization if thresholds didn't change. */
if (sensor_mgr->active_thresh_valid &&
sensor_mgr->update_thresholds) {
sensor_mgr->update_thresholds(sensor_mgr);//更新sensor的threshold
}
if (!sensor_mgr->req_active && active_req) {
/* Advertise there is now an active request available */
pthread_mutex_lock(&(sensor_mgr->req_wait_mutex));
sensor_mgr->req_active = 1;
pthread_cond_broadcast(&(sensor_mgr->req_wait_cond));
pthread_mutex_unlock(&(sensor_mgr->req_wait_mutex));
} else {
sensor_mgr->req_active = active_req;
}
THERM_MUTEX_UNLOCK(&ts_clnt_mtx);
return 0;
}
我们再来看上面这个sensor的update_thresholds函数
void tsens_sensor_update_thresholds(struct sensor_info *sensor,
struct thresholds_req_t *thresh)
{
struct tsens_data *tsens;
if (NULL == thresh ||
NULL == sensor ||
NULL == sensor->data) {
msg("%s: unexpected NULL", __func__);
return;
}
tsens = (struct tsens_data *) sensor->data;
/* Convert thresholds to Celsius for TSENS*/
thresh->high = RCONV(thresh->high);
thresh->low = RCONV(thresh->low);
set_thresholds(tsens, thresh);
}
主要还是看set_thresholds函数,这个函数主要会去设置 /sys/devices/virtual/thermal/thermal_zone%d/trip_point_%d_temp,其中一个是threshold的low,另一个是threshold的high,设置完之后还需要对/sys/devices/virtual/thermal/thermal_zone%d/trip_point_%d_type节点设置enabled或者disabled(注意这个里的enabled和disabled只是对sensor驱动下一次中断而言)。这样当sensor检测到温度大于high或者小于low,这个时候/sys/devices/virtual/thermal/thermal_zone%d/type节点就会有事件了,sensor_wait就不会去wait了,这样就可以调用各个client的回调来开启各个配置算法的流程。
static void set_thresholds(struct tsens_data *tsens, struct thresholds_req_t *thresh)
{
char minname[MAX_PATH]= {0};
char maxname[MAX_PATH]= {0};
char buf[LVL_BUF_MAX] = {0};
int ret = 0;
int mintemp = 0;
if (NULL == tsens) {
msg("%s: unexpected NULL", __func__);
return;
}
snprintf(minname, MAX_PATH, TSENS_TZ_TRIP_TEMP, tsens->sensor->tzn, tsens->trip_min);
snprintf(maxname, MAX_PATH, TSENS_TZ_TRIP_TEMP, tsens->sensor->tzn, tsens->trip_max);
/* Set thresholds in legal order */
if (read_line_from_file(minname, buf, sizeof(buf)) > 0) {
mintemp = atoi(buf);
}
if (thresh->high >= (mintemp / tsens->sensor->scaling_factor)) {
/* set high threshold first */
if (thresh->high_valid) {
dbgmsg("Setting up TSENS thresholds high: %d\n", thresh->high);
snprintf(buf, LVL_BUF_MAX, "%d", thresh->high * tsens->sensor->scaling_factor);
ret = write_to_file(maxname, buf, strlen(buf));
if (ret <= 0)
msg("TSENS threshold high failed to set %d\n", thresh->high);
}
enable_threshold(tsens, tsens->trip_max, thresh->high_valid);
if (thresh->low_valid) {
dbgmsg("Setting up TSENS thresholds low: %d\n", thresh->low);
snprintf(buf, LVL_BUF_MAX, "%d", thresh->low * tsens->sensor->scaling_factor);
ret = write_to_file(minname, buf, strlen(buf));
if (ret <= 0)
msg("TSENS threshold low failed to set %d\n", thresh->low);
}
enable_threshold(tsens, tsens->trip_min, thresh->low_valid);
} else {
if (thresh->low_valid) {
dbgmsg("Setting up TSENS thresholds low: %d\n", thresh->low);
snprintf(buf, LVL_BUF_MAX, "%d", thresh->low * tsens->sensor->scaling_factor);
ret = write_to_file(minname, buf, strlen(buf));
if (ret <= 0)
msg("TSENS threshold low failed to set %d\n", thresh->low);
}
enable_threshold(tsens, tsens->trip_min, thresh->low_valid);
if (thresh->high_valid) {
dbgmsg("Setting up TSENS thresholds high: %d\n", thresh->high);
snprintf(buf, LVL_BUF_MAX, "%d", thresh->high * tsens->sensor->scaling_factor);
ret = write_to_file(maxname, buf, strlen(buf));
if (ret <= 0)
msg("TSENS threshold high failed to set %d\n", thresh->high);
}
enable_threshold(tsens, tsens->trip_max, thresh->high_valid);
}
}
上面我们基本分析了sensor监控温度的流程,上面我们分析的是tsens的sensor,下面我们再来看看下面sensor。有区分sensor的类型来做处理,有没有update_thresholds函数。有没有interrupt_wait函数的,如果没有interrupt_wait就是用usleep函数来达到wait的目的,wait的interval就是用算法配置中的采样率。
static int add_tgt_gen_sensors(char *sensor_name, struct msm_sensor_info *sens_info)
{
int ret_val = 0;
struct sensor_info *sensor;
sensor = malloc(sizeof(struct sensor_info));
if (sensor == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor, 0, sizeof(struct sensor_info));
sensor->name = malloc(MAX_SENSOR_NAME_LEN);
if (sensor->name == NULL) {
msg("%s: malloc failed.\n", __func__);
ret_val = -(ENOMEM);
goto error_handler;
}
memset(sensor->name, 0, MAX_SENSOR_NAME_LEN);
strlcpy(sensor->name, sensor_name, MAX_SENSOR_NAME_LEN);
sensor->setup = thermal_sensor_setup;
sensor->shutdown = thermal_sensor_shutdown;
sensor->get_temperature = thermal_sensor_get_temperature;
sensor->get_trip_temperature = NULL;
sensor->update_thresholds = NULL;
sensor->scaling_factor = sens_info->scaling_factor;
if (!strncmp(sens_info->type, ALARM_TYPE, strlen(ALARM_TYPE))) {
sensor->interrupt_enable = 1;
sensor->interrupt_wait = thermal_sensor_interrupt_wait;//alarm类型sensor有wait函数,但是没有threshold
} else if (!strncmp(sens_info->type, USERSPACE_TYPE,
strlen(USERSPACE_TYPE))) {
sensor->interrupt_enable = 1;
sensor->interrupt_wait = thermal_sensor_interrupt_wait;
sensor->update_thresholds = thermal_sensor_update_thresholds;
sensor->get_trip_temperature = thermal_sensor_get_trip_temp;
sensor->scaling_factor = 1000;
} else {
sensor->interrupt_enable = 0;//这个interrupt不允许
sensor->interrupt_wait = NULL;
}
pthread_mutex_init(&(sensor->read_mtx), NULL);
sensor->tzn = 0;
sensor->data = NULL;
add_tgt_sensor(sensor);
error_handler:
if (ret_val) {
if (sensor) {
if (sensor->name)
free(sensor->name);
free(sensor);
}
}
return ret_val;
}
这样sensor监控温度,sensor_monitor函数wait如何唤醒,以及如何启动配置算法的流程,都分析清楚了。