int csys_fs::read(const std::string &path, std::string &buf) { std::string p = base_path + path; int ret = 0; #ifndef ANDROID try { #endif std::ifstream f(p.c_str(), std::fstream::in); if (f.fail()) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -EINVAL; } f >> buf; if (f.bad()) { thd_log_warn("sysfs read failed %s\n", path.c_str()); ret = -EIO; } f.close(); #ifndef ANDROID } catch (const std::ifstream::failure& e) { thd_log_warn("csys_fs::read exception %s\n", path.c_str()); ret = -EIO; } #endif return ret; }
int csys_fs::read(const std::string &path, char *buf, int len) { std::string p = base_path + path; int fd = ::open(p.c_str(), O_RDONLY); if (fd < 0) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -errno; } int ret = ::read(fd, buf, len); if (ret < 0) thd_log_warn("sysfs read failed %s\n", path.c_str()); close(fd); return ret; }
int csys_fs::write(const std::string &path, const std::string &buf) { std::string p = base_path + path; int fd = ::open(p.c_str(), O_WRONLY); if (fd < 0) { thd_log_warn("sysfs write failed %s\n", path.c_str()); return -errno; } int ret = ::write(fd, buf.c_str(), buf.size()); if (ret < 0) thd_log_warn("sysfs write failed %s\n", path.c_str()); close(fd); return ret; }
static void *temp_thread_loop(void *arg) { cthd_topology *obj = (cthd_topology*)arg; cpu_set_t set; unsigned char cpu_mask = 0xff; cpu_mask &= ~(1 << obj->designated_cpu); CPU_ZERO(&set); CPU_SET(obj->designated_cpu, &set); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); if(sched_setaffinity(gettid(), sizeof(cpu_set_t), &set)) { perror("sched_setaffinity"); return NULL; } obj->cal_failed = false; for(;;) { if(obj->terminate_thread) break; sleep(1); if(obj->check_load_for_calibration(cpu_mask) == false) { obj->cal_failed = true; obj->terminate_thread = true; thd_log_warn("!unsuitable CPU load \n"); break; } obj->temp_function(); } return NULL; }
// signal handler static void signal_handler(int sig) { switch (sig) { case SIGHUP: thd_log_warn("Received SIGHUP signal. \n"); break; case SIGINT: case SIGTERM: thd_log_info("Daemon exiting \n"); daemonShutdown(); exit(EXIT_SUCCESS); break; default: thd_log_warn("Unhandled signal %s", strsignal(sig)); break; } }
int cthd_msr::set_clock_mod_duty_cycle_per_cpu(int cpu, int state) { unsigned long long val; int ret; // First bit is reserved state = state << 1; ret = read_msr(cpu, MSR_IA32_THERM_CONTROL, &val); if (ret < 0) return THD_ERROR; if (!state) { val &= ~MSR_IA32_CLK_MOD_ENABLE; } else { val |= MSR_IA32_CLK_MOD_ENABLE; } val &= ~MSR_IA32_CLK_MOD_DUTY_CYCLE_MASK; val |= (state & MSR_IA32_CLK_MOD_DUTY_CYCLE_MASK); ret = write_msr(cpu, MSR_IA32_THERM_CONTROL, val); if (ret < 0) { thd_log_warn("set_clock_mod_duty_cycle current set failed to write\n"); return THD_ERROR; } return THD_SUCCESS; }
int cthd_parse::parser_init() { doc = xmlReadFile(filename.c_str(), NULL, 0); if (doc == NULL) { thd_log_warn("error: could not parse file %s\n", filename.c_str()); return THD_ERROR; } root_element = xmlDocGetRootElement(doc); if (root_element == NULL) { thd_log_warn("error: could not get root element \n"); return THD_ERROR; } return THD_SUCCESS; }
int csys_fs::read(const std::string &path, std::string &buf) { std::string p = base_path + path; std::ifstream f(p.c_str(), std::fstream::in); if (f.fail()) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -EINVAL; } int ret = 0; f >> buf; if (f.bad()) { thd_log_warn("sysfs read failed %s\n", path.c_str()); ret = -EIO; } f.close(); return ret; }
int csys_fs::write(const std::string &path, unsigned int position, unsigned long long data) { std::string p = base_path + path; int fd = ::open(p.c_str(), O_WRONLY); if (fd < 0) { thd_log_warn("sysfs write failed %s\n", path.c_str()); return -errno; } if (::lseek(fd, position, SEEK_CUR) == -1) { thd_log_warn("sysfs write failed %s\n", path.c_str()); return -errno; } int ret = ::write(fd, &data, sizeof(data)); if (ret < 0) thd_log_warn("sysfs write failed %s\n", path.c_str()); close(fd); return ret; }
int csys_fs::read(const std::string &path, unsigned int position, char *buf, int len) { std::string p = base_path + path; int fd = ::open(p.c_str(), O_RDONLY); if (fd < 0) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -errno; } if (::lseek(fd, position, SEEK_CUR) == -1) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -errno; } int ret = ::read(fd, buf, len); if (ret < 0) thd_log_warn("sysfs read failed %s\n", path.c_str()); close(fd); return ret; }
int csys_fs::read(const std::string &path, unsigned long *ptr_val) { std::string p = base_path + path; char str[32]; int ret; int fd = ::open(p.c_str(), O_RDONLY); if (fd < 0) { thd_log_warn("sysfs read failed %s\n", path.c_str()); return -errno; } ret = ::read(fd, str, sizeof(str)); if (ret > 0) *ptr_val = atol(str); else thd_log_warn("sysfs read failed %s\n", path.c_str()); close(fd); return ret; }
int csys_fs::read_symbolic_link_value(const std::string &path, char *buf, int len) { std::string p = base_path + path; int ret = ::readlink(p.c_str(), buf, len); if (ret < 0) { thd_log_warn("read_symbolic_link %s\n", path.c_str()); return -errno; } buf[ret] = '\0'; return 0; }
int cthd_msr::write_msr(int cpu, unsigned int idx, unsigned long long val) { int ret = -1; std::stringstream file_name_str; file_name_str << cpu << "/msr"; if (msr_sysfs.exists(file_name_str.str())) { ret = msr_sysfs.write(file_name_str.str(), idx, val); } if (ret < 0) { thd_log_warn("MSR WRITE Failed \n"); } return ret; }
int cthd_msr::read_msr(int cpu, unsigned int idx, unsigned long long *val) { int ret = -1; std::stringstream file_name_str; file_name_str << cpu << "/msr"; if (msr_sysfs.exists(file_name_str.str())) { ret = msr_sysfs.read(file_name_str.str(), idx, (char*) val, sizeof(*val)); } if (ret < 0) { thd_log_warn("MSR READ Failed \n"); } return ret; }
cthd_rapl_power_meter::cthd_rapl_power_meter(unsigned int mask) : rapl_present(true), rapl_sysfs("/sys/class/powercap/intel-rapl/"), domain_list( 0), last_time(0), poll_thread(0), measure_mask(mask), enable_measurement( false) { if (rapl_sysfs.exists()) { thd_log_debug("RAPL sysfs present \n"); rapl_present = true; last_time = time(NULL); rapl_read_domains(rapl_sysfs.get_base_path()); } else { thd_log_warn("NO RAPL sysfs present \n"); rapl_present = false; } }
int cthd_trip_point::thd_trip_point_add_cdev_index(int _index, int influence) { cthd_cdev *cdev = thd_engine->thd_get_cdev_at_index(_index); if (cdev) { trip_pt_cdev_t thd_cdev; thd_cdev.cdev = cdev; thd_cdev.influence = influence; thd_cdev.sampling_priod = 0; thd_cdev.last_op_time = 0; trip_cdev_add(thd_cdev); return THD_SUCCESS; } else { thd_log_warn("thd_trip_point_add_cdev_index not present %d\n", _index); return THD_ERROR; } }
int cthd_zone_surface::read_trip_points() { cthd_trip_point *trip_ptr = NULL; bool add = false; if (!sensor) return THD_ERROR; for (unsigned int j = 0; j < trip_points.size(); ++j) { if (trip_points[j].get_trip_type() == PASSIVE) { thd_log_debug("updating existing trip temp \n"); trip_points[j].update_trip_temp(passive_trip_temp); trip_points[j].update_trip_hyst(passive_trip_hyst); trip_ptr = &trip_points[j]; break; } } if (!trip_ptr) { trip_ptr = new cthd_trip_point(trip_points.size(), PASSIVE, passive_trip_temp, passive_trip_hyst, index, sensor->get_index(), SEQUENTIAL); if (!trip_ptr) { thd_log_warn("Mem alloc error for new trip \n"); return THD_ERROR; } add = true; } cthd_cdev *cdev = thd_engine->search_cdev("rapl_controller"); if (cdev) { trip_ptr->thd_trip_point_add_cdev(*cdev, cthd_trip_point::default_influence, surface_sampling_period); } cdev = thd_engine->search_cdev("intel_powerclamp"); if (cdev) { trip_ptr->thd_trip_point_add_cdev(*cdev, cthd_trip_point::default_influence, surface_sampling_period); } if (add) { trip_points.push_back(*trip_ptr); } return THD_SUCCESS; }
int cthd_kobj_uevent::kobj_uevent_open() { memset(&nls, 0, sizeof(struct sockaddr_nl)); nls.nl_family = AF_NETLINK; nls.nl_pid = getpid(); nls.nl_groups = -1; fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (fd < 0) return fd; if (bind(fd, (struct sockaddr*) &nls, sizeof(struct sockaddr_nl))) { thd_log_warn("kob_uevent bin failed \n"); close(fd); return -1; } return fd; }
int cthd_msr::set_clock_mod_duty_cycle(int state) { int cpu_count = get_no_cpus(); unsigned long long val; int ret; thd_log_info("Set T stated %d \n", state); // First bit is reserved state = state << 1; for (int i = 0; i < cpu_count; ++i) { ret = read_msr(i, MSR_IA32_THERM_CONTROL, &val); if (ret < 0) { thd_log_debug("set_clock_mod_duty_cycle current MSR read failed\n"); return THD_ERROR; } thd_log_debug("set_clock_mod_duty_cycle current %x\n", (unsigned int) val); if (!state) { val &= ~MSR_IA32_CLK_MOD_ENABLE; } else { val |= MSR_IA32_CLK_MOD_ENABLE; } val &= ~MSR_IA32_CLK_MOD_DUTY_CYCLE_MASK; val |= (state & MSR_IA32_CLK_MOD_DUTY_CYCLE_MASK); thd_log_debug("set_clock_mod_duty_cycle current set to %x\n", (unsigned int) val); ret = write_msr(i, MSR_IA32_THERM_CONTROL, val); if (ret < 0) { thd_log_warn( "set_clock_mod_duty_cycle current set failed to write\n"); return THD_ERROR; } } return THD_SUCCESS; }
bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, int pref, bool *reset) { int on = -1; int off = -1; bool apply = false; *reset = false; if (depend_cdev && read_temp >= temp) { int _state = depend_cdev->get_curr_state(); int valid = 0; switch (depend_cdev_state_rel) { case EQUAL: if (_state == depend_cdev_state) valid = 1; break; case GREATER: if (_state > depend_cdev_state) valid = 1; break; case LESSER: if (_state < depend_cdev_state) valid = 1; break; case LESSER_OR_EQUAL: if (_state <= depend_cdev_state) valid = 1; break; case GREATER_OR_EQUAL: if (_state >= depend_cdev_state) valid = 1; break; default: break; } if (!valid) { thd_log_info("constraint failed %s:%d:%d:%d \n", depend_cdev->get_cdev_type().c_str(), _state, depend_cdev_state_rel, depend_cdev_state); return false; } } if (sensor_id != DEFAULT_SENSOR_ID && sensor_id != id) return false; if (read_temp == 0) { thd_log_debug("TEMP == 0 pref: %d\n", pref); } if (type == CRITICAL) { int ret = -1; if (read_temp >= temp) { thd_log_warn("critical temp reached \n"); sync(); #ifdef ANDROID ret = property_set("sys.powerctl", "shutdown,thermal"); #else reboot(RB_POWER_OFF); #endif if (ret != 0) thd_log_warn("power off failed ret=%d err=%s\n", ret, strerror(errno)); else thd_log_warn("power off initiated\n"); return true; } } if (type == HOT) { if (read_temp >= temp) { thd_log_warn("Hot temp reached \n"); csys_fs power("/sys/power/"); power.write("state", "mem"); return true; } } if (type == POLLING && sensor_id != DEFAULT_SENSOR_ID) { cthd_sensor *sensor = thd_engine->get_sensor(sensor_id); if (sensor) { if (!poll_on && read_temp >= temp) { thd_log_debug("polling trip reached, on \n"); sensor->sensor_poll_trip(true); poll_on = true; sensor->sensor_fast_poll(true); if (sensor->check_async_capable()) sensor->set_threshold(0, temp); } else if (poll_on && read_temp < temp) { sensor->sensor_poll_trip(false); thd_log_debug("Dropped below poll threshold \n"); *reset = true; poll_on = false; sensor->sensor_fast_poll(false); if (sensor->check_async_capable()) sensor->set_threshold(0, temp); } } return true; } thd_log_debug("pref %d type %d temp %d trip %d \n", pref, type, read_temp, temp); switch (pref) { case PREF_DISABLED: return false; break; case PREF_PERFORMANCE: if (type == ACTIVE || type == MAX) { apply = true; thd_log_debug("Active Trip point applicable \n"); } break; case PREF_ENERGY_CONSERVE: if (type == PASSIVE || type == MAX) { apply = true; thd_log_debug("Passive Trip point applicable \n"); } break; default: break; } if (apply) { if (read_temp >= temp) { thd_log_debug("Trip point applicable > %d:%d \n", index, temp); on = 1; trip_on = true; } else if ((trip_on && (read_temp + hyst) < temp) || (!trip_on && read_temp < temp)) { thd_log_debug("Trip point applicable < %d:%d \n", index, temp); off = 1; trip_on = false; } } else return false; if (on != 1 && off != 1) return true; int i, ret; thd_log_debug("cdev size for this trippoint %lu\n", (unsigned long) cdevs.size()); if (on > 0) { for (unsigned i = 0; i < cdevs.size(); ++i) { cthd_cdev *cdev = cdevs[i].cdev; if (cdevs[i].sampling_priod) { time_t tm; time(&tm); if ((tm - cdevs[i].last_op_time) < cdevs[i].sampling_priod) { #if defined __x86_64__ && defined __ILP32__ thd_log_info("Too early to act index %d tm %lld\n", cdev->thd_cdev_get_index(), tm - cdevs[i].last_op_time); #else thd_log_info("Too early to act index %d tm %ld\n", cdev->thd_cdev_get_index(), tm - cdevs[i].last_op_time); #endif break; } cdevs[i].last_op_time = tm; } thd_log_debug("cdev at index %d:%s\n", cdev->thd_cdev_get_index(), cdev->get_cdev_type().c_str()); /* * When the cdev is already in max state, we skip this cdev. * Also when the target state if any for the current trip is greater * or equal than the current state of the cdev, then also skip. */ if (cdev->in_max_state() || (cdevs[i].target_state_valid && cdev->cmp_current_state( cdev->map_target_state( cdevs[i].target_state_valid, cdevs[i].target_state)) <= 0)) { thd_log_debug("Need to switch to next cdev target %d \n", cdev->map_target_state(cdevs[i].target_state_valid, cdevs[i].target_state)); // No scope of control with this cdev continue; } if (cdevs[i].target_state == TRIP_PT_INVALID_TARGET_STATE) cdevs[i].target_state = cdev->get_min_state(); ret = cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), 1, zone_id, index, cdevs[i].target_state_valid, cdev->map_target_state(cdevs[i].target_state_valid, cdevs[i].target_state), &cdevs[i].pid_param, cdevs[i].pid, false); if (control_type == SEQUENTIAL && ret == THD_SUCCESS) { // Only one cdev activation break; } } } if (off > 0) { for (i = cdevs.size() - 1; i >= 0; --i) { cthd_cdev *cdev = cdevs[i].cdev; thd_log_debug("cdev at index %d:%s\n", cdev->thd_cdev_get_index(), cdev->get_cdev_type().c_str()); if (cdev->in_min_state()) { thd_log_debug("Need to switch to next cdev \n"); // No scope of control with this cdev continue; } if (cdevs[i].target_state == TRIP_PT_INVALID_TARGET_STATE) cdevs[i].target_state = cdev->get_min_state(); cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), 0, zone_id, index, cdevs[i].target_state_valid, cdev->map_target_state(cdevs[i].target_state_valid, cdevs[i].target_state), &cdevs[i].pid_param, cdevs[i].pid, false); if (control_type == SEQUENTIAL) { // Only one cdev activation break; } } } return true; }
// Setup dbus server static int thd_dbus_server_proc(gboolean no_daemon) { DBusGConnection *bus; DBusGProxy *bus_proxy; GMainLoop *main_loop; GError *error = NULL; guint result; PrefObject *value_obj; thd_engine = NULL; // Initialize the GType/GObject system g_type_init(); // Create a main loop that will dispatch callbacks g_main_loop = main_loop = g_main_loop_new(NULL, FALSE); if (main_loop == NULL) { thd_log_error("Couldn't create GMainLoop:"); return THD_FATAL_ERROR; } if (dbus_enable) { bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); if (error != NULL) { thd_log_error("Couldn't connect to session bus: %s:", error->message); return THD_FATAL_ERROR; } // Get a bus proxy instance bus_proxy = dbus_g_proxy_new_for_name(bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); if (bus_proxy == NULL) { thd_log_error("Failed to get a proxy for D-Bus:"); return THD_FATAL_ERROR; } thd_log_debug("Registering the well-known name (%s)\n", THD_SERVICE_NAME); // register the well-known name if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING, THD_SERVICE_NAME, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) { thd_log_error("D-Bus.RequestName RPC failed: %s\n", error->message); return THD_FATAL_ERROR; } thd_log_debug("RequestName returned %d.\n", result); if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { thd_log_error("Failed to get the primary well-known name:"); return THD_FATAL_ERROR; } value_obj = (PrefObject*) g_object_new(PREF_TYPE_OBJECT, NULL); if (value_obj == NULL) { thd_log_error("Failed to create one Value instance:"); return THD_FATAL_ERROR; } thd_log_debug("Registering it on the D-Bus.\n"); dbus_g_connection_register_g_object(bus, THD_SERVICE_OBJECT_PATH, G_OBJECT(value_obj)); } if (!no_daemon) { printf("Ready to serve requests: Daemonizing.. %d\n", thd_daemonize); thd_log_info( "thermald ver %s: Ready to serve requests: Daemonizing..\n", TD_DIST_VERSION); if (daemon(0, 1) != 0) { thd_log_error("Failed to daemonize.\n"); return THD_FATAL_ERROR; } } thd_engine = new cthd_engine_default(); if (exclusive_control) thd_engine->set_control_mode(EXCLUSIVE); // Initialize thermald objects thd_engine->set_poll_interval(thd_poll_interval); if (thd_engine->thd_engine_start(ignore_cpuid_check) != THD_SUCCESS) { thd_log_error("THD engine start failed: "); closelog(); exit(1); } // Start service requests on the D-Bus thd_log_debug("Start main loop\n"); g_main_loop_run(main_loop); thd_log_warn("Oops g main loop exit..\n"); return THD_SUCCESS; }
bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, int pref, bool *reset) { int on = -1; int off = -1; bool apply = false; *reset = false; if (sensor_id != DEFAULT_SENSOR_ID && sensor_id != id) return false; if (read_temp == 0) { thd_log_warn("TEMP == 0 pref: %d\n", pref); } if (type == CRITICAL) { if (read_temp >= temp) { thd_log_warn("critical temp reached \n"); sync(); reboot(RB_POWER_OFF); } } if (type == POLLING && sensor_id != DEFAULT_SENSOR_ID) { cthd_sensor *sensor = thd_engine->get_sensor(sensor_id); if (sensor && sensor->check_async_capable()) { if (!poll_on && read_temp >= temp) { thd_log_debug("polling trip reached, on \n"); sensor->sensor_poll_trip(true); poll_on = true; sensor->set_threshold(0, temp); } else if (poll_on && read_temp < temp) { thd_log_debug("polling trip reached, off \n"); sensor->sensor_poll_trip(false); thd_log_info("Dropped below poll threshold \n"); *reset = true; poll_on = false; sensor->set_threshold(0, temp); } } return true; } thd_log_debug("pref %d type %d temp %d trip %d \n", pref, type, read_temp, temp); switch (pref) { case PREF_DISABLED: return false; break; case PREF_PERFORMANCE: if (type == ACTIVE || type == MAX) { apply = true; thd_log_debug("Active Trip point applicable \n"); } break; case PREF_ENERGY_CONSERVE: if (type == PASSIVE || type == MAX) { apply = true; thd_log_debug("Passive Trip point applicable \n"); } break; default: break; } if (apply) { if (read_temp >= temp) { thd_log_debug("Trip point applicable > %d:%d \n", index, temp); on = 1; trip_on = true; } else if ((trip_on && (read_temp + hyst) < temp) || (!trip_on && read_temp < temp)) { thd_log_debug("Trip point applicable < %d:%d \n", index, temp); off = 1; trip_on = false; } } else return false; if (on != 1 && off != 1) return true; int i, ret; thd_log_debug("cdev size for this trippoint %lu\n", (unsigned long) cdevs.size()); if (on > 0) { for (unsigned i = 0; i < cdevs.size(); ++i) { cthd_cdev *cdev = cdevs[i].cdev; if (cdevs[i].sampling_priod) { time_t tm; time(&tm); if ((tm - cdevs[i].last_op_time) < cdevs[i].sampling_priod) { thd_log_info("Too early to act index %d tm %ld\n", cdev->thd_cdev_get_index(), tm - cdevs[i].last_op_time); continue; } cdevs[i].last_op_time = tm; } thd_log_debug("cdev at index %d:%s\n", cdev->thd_cdev_get_index(), cdev->get_cdev_type().c_str()); if (cdev->in_max_state()) { thd_log_debug("Need to switch to next cdev \n"); // No scope of control with this cdev continue; } ret = cdev->thd_cdev_set_state(temp, temp, read_temp, 1, zone_id); if (control_type == SEQUENTIAL && ret == THD_SUCCESS) { // Only one cdev activation break; } } } if (off > 0) { for (i = cdevs.size() - 1; i >= 0; --i) { cthd_cdev *cdev = cdevs[i].cdev; thd_log_debug("cdev at index %d:%s\n", cdev->thd_cdev_get_index(), cdev->get_cdev_type().c_str()); if (cdev->in_min_state()) { thd_log_debug("Need to switch to next cdev \n"); // No scope of control with this cdev continue; } cdev->thd_cdev_set_state(temp, temp, read_temp, 0, zone_id); if (control_type == SEQUENTIAL) { // Only one cdev activation break; } } } return true; }
int cthd_topology::calibrate() { int ret; int i, j; // Reset moving average memset(temp_data, 0, sizeof(*temp_data) * no_sensors); for(i = 0; i < no_cpu; ++i) { cpu_sensor_rel[i].sensor_id = - 1; } for(i = 0; i < no_sensors; ++i) { sensor_cpu_rel[i].cpu_id = - 1; } for(i = 0; i < no_cpu; ++i) { int max = 0; int max_index = 0; int diff; if(check_load_for_calibration(0xff) == false) { // Not a right time to do calibration // retry at later time thd_log_warn("Calibration process aborted because of unsuitable CPU load \n") ; return - 1; } designated_cpu = i; memset(temp_data, 0, sizeof(*temp_data) *no_sensors); pthread_attr_init(&thd_attr); pthread_attr_setdetachstate(&thd_attr, PTHREAD_CREATE_DETACHED); terminate_thread = false; ret = pthread_create(&load_thread, &thd_attr, load_thread_loop, (void*)this); ret = pthread_create(&temp_thread, &thd_attr, temp_thread_loop, (void*)this); thd_log_info("Started %d seconds sleep on main thread \n", measurment_time); sleep(measurment_time); thd_log_info("End %d seconds sleep on main thread \n", measurment_time); terminate_thread = true; sleep(1); pthread_cancel(load_thread); pthread_cancel(temp_thread); if(cal_failed) { thd_log_warn("Calibration process aborted because of unsuitable CPU load \n") ; return - 1; } for(int j = 0; j < no_sensors; ++j) { diff = temp_data[j].last_moving_average; if(diff == 0) continue; if(max < diff) { max = diff; max_index = j; } cpu_sensor_rel[i].sensor_id = max_index; thd_log_info("cpu %d sensor %d current %d max %d:%d\n", i, j, diff, max_index, max); } } // Sanitize bool valid = true; for(i = 0; i < no_cpu; ++i) { int count = 0; unsigned int mask = 0; for(j = 0; j < no_sensors; ++j) { if(i != j && cpu_sensor_rel[j].sensor_id != - 1 && cpu_sensor_rel[i].sensor_id == cpu_sensor_rel[j].sensor_id) { count++; mask |= ((1 << i) | (1 << j)); sensor_cpu_rel[cpu_sensor_rel[i].sensor_id].cpu_id = mask; if(count > 2) { valid = false; break; } } } } // Check if every CPU is covered if(valid) { for(i = 0; i < no_cpu; ++i) { if(cpu_sensor_rel[i].sensor_id == - 1) { valid = false; break; } } } if(valid) { for(i = 0; i < no_cpu; ++i) { //if (cpu_sensor_rel[i].sensor_id != -1) thd_log_info("cpu_sensor_rel cpu%d sensor %d\n", i, cpu_sensor_rel[i].sensor_id); } for(i = 0; i < no_sensors; ++i) { if(sensor_cpu_rel[i].cpu_id != - 1) { thd_log_info("sensor_cpu rel sensor %d cpu %x\n", i, sensor_cpu_rel[i].cpu_id); store_configuration(i, sensor_cpu_rel[i].cpu_id); } } } else { thd_log_info("Can't reliably tie sensor and CPU\n"); } configuration_saved(); return 0; // calibration process is done, it is possible that we can't do per cpu control }
// Setup dbus server static int thd_dbus_server_proc(gboolean no_daemon) { DBusGConnection *bus; DBusGProxy *bus_proxy; GMainLoop *main_loop; GError *error = NULL; guint result; PrefObject *value_obj; // Initialize the GType/GObject system g_type_init(); // Create a main loop that will dispatch callbacks main_loop = g_main_loop_new(NULL, FALSE); if(main_loop == NULL) { thd_log_error("Couldn't create GMainLoop:"); return THD_FATAL_ERROR; } if(dbus_enable) { bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); if(error != NULL) { thd_log_error("Couldn't connect to session bus: %s:", error->message); return THD_FATAL_ERROR; } // Get a bus proxy instance bus_proxy = dbus_g_proxy_new_for_name(bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); if(bus_proxy == NULL) { thd_log_error("Failed to get a proxy for D-Bus:"); return THD_FATAL_ERROR; } thd_log_debug("Registering the well-known name (%s)\n", THD_SERVICE_NAME); // register the well-known name if(!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING, THD_SERVICE_NAME, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) { thd_log_error("D-Bus.RequestName RPC failed: %s\n", error->message); return THD_FATAL_ERROR; } thd_log_debug("RequestName returned %d.\n", result); if(result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { thd_log_error("Failed to get the primary well-known name:"); return THD_FATAL_ERROR; } value_obj = (PrefObject*)g_object_new(PREF_TYPE_OBJECT, NULL); if(value_obj == NULL) { thd_log_error("Failed to create one Value instance:"); return THD_FATAL_ERROR; } thd_log_debug("Registering it on the D-Bus.\n"); dbus_g_connection_register_g_object(bus, THD_SERVICE_OBJECT_PATH, G_OBJECT (value_obj)); } if(!no_daemon) { printf("Ready to serve requests: Daemonizing.. %d\n", thd_daemonize); thd_log_info("thermald ver %s: Ready to serve requests: Daemonizing..\n", TD_DIST_VERSION); if(daemon(0, 1) != 0) { thd_log_error("Failed to daemonize.\n"); return THD_FATAL_ERROR; } } if(use_thermal_sys_fs) thd_engine = new cthd_engine_therm_sysfs(); else { cthd_parse parser; bool matched = false; // if there is XML config for this platform // Use this instead of default DTS sensor and associated cdevs if(parser.parser_init() == THD_SUCCESS) { if(parser.start_parse() == THD_SUCCESS) { matched = parser.platform_matched(); } } if (matched) { thd_log_warn("UUID matched, so will load zones and cdevs from thermal-conf.xml\n"); thd_engine = new cthd_engine_therm_sysfs(); } else thd_engine = new cthd_engine_dts(); } // Initialize thermald objects if(thd_engine->thd_engine_start() != THD_SUCCESS) { thd_log_error("THD engine start failed: "); closelog(); exit(1); } // Start service requests on the D-Bus thd_log_debug("Start main loop\n"); g_main_loop_run(main_loop); thd_log_warn("Oops g main loop exit..\n"); return THD_SUCCESS; }