コード例 #1
0
void cthd_cdev_rapl_msr::set_curr_state(int state, int arg)
{
	int new_state;

	if (!control_start && state == inc_dec_val) {
		thd_log_debug("rapl state control begin\n");
		rapl.store_pkg_power_limit();
		control_start = true;
	}
	if (state < inc_dec_val)
	{
		new_state = 0;
		curr_state = 0;
	}
	else
	{
		new_state = phy_max - state;
		curr_state = state;
		thd_log_debug("rapl state = %d new_state = %d\n", state, new_state);
		rapl.set_pkg_power_limit(1, new_state); //thd_engine->def_poll_interval/1000 - 1, new_state);
	}

	if (state < inc_dec_val) {
		thd_log_debug("rapl state control end\n");
		rapl.restore_pkg_power_limit();
		control_start = false;
	}
}
コード例 #2
0
ファイル: main.cpp プロジェクト: RAOF/thermal_daemon
// Callback function called to get value via dbus
gboolean thd_dbus_interface_get_current_preference(PrefObject *obj, gdouble
	*value_out, GError **error)
{
	thd_log_debug("thd_dbus_interface_get_current_preference\n");
	g_assert(obj != NULL);

	cthd_preference thd_pref;
	value_out = (gdouble*)thd_pref.get_preference_cstr();
	thd_log_debug("thd_dbus_interface_get_current_preference out :%s\n", (char*)
	value_out);

	return TRUE;
}
コード例 #3
0
int cthd_nl_wrapper::genl_parse_event_message(const struct sockaddr_nl *who,
		 struct nlmsghdr *n, void *arg)
{
	struct rtattr *tb[ACPI_GENL_ATTR_MAX + 1];
	struct genlmsghdr *ghdr = (struct genlmsghdr *)NLMSG_DATA(n);
	int len = n->nlmsg_len;
	struct rtattr *attrs;

	if (n->nlmsg_type != acpi_event_family_id) {
		fprintf(stderr, "Not a acpi event message, nlmsg_len=%d "
			"nlmsg_type=0x%x\n", n->nlmsg_len, n->nlmsg_type);
		return 0;
	}

	len -= NLMSG_LENGTH(GENL_HDRLEN);

	if (len < 0) {
		fprintf(stderr, "wrong controller message len %d\n", len);
		return -1;
	}

	attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN);
	parse_rtattr(tb, ACPI_GENL_ATTR_MAX, attrs, len);

	if (tb[ACPI_GENL_ATTR_EVENT]) {
		struct acpi_genl_event *event =
		    (struct acpi_genl_event *)RTA_DATA(tb[ACPI_GENL_ATTR_EVENT]);

		if (!strcmp(event->device_class, "thermal_zone")) {
			thermal_zone_notify_t msg;
			char *zone_str;
			msg.zone = 0;
			if (!strncmp(event->bus_id, "LNXTHERM:", strlen("LNXTHERM:")))
			{
				zone_str = event->bus_id + strlen("LNXTHERM:");
				sscanf(zone_str, "%d", &msg.zone);
				thd_log_debug("matched %s\n", zone_str);
			}
			msg.type = event->type;
			msg.data = event->data;
			thd_engine->send_message(THERMAL_ZONE_NOTIFY, sizeof(msg), (unsigned char*)&msg);

			thd_log_debug("%15s[zone %d] %08x %08x\n", event->bus_id,
					msg.zone, event->type, event->data);
		}
		return 0;
	}

	return -1;

}
コード例 #4
0
int cthd_msr::get_clock_mod_duty_cycle() {
	int ret, state = 0;
	unsigned long long val;

	// Just get for cpu 0 and return
	ret = read_msr(0, MSR_IA32_THERM_CONTROL, &val);
	thd_log_debug("get_clock_mod_duty_cycle current %x\n", (unsigned int) val);
	if (ret < 0)
		return THD_ERROR;

	if (val & MSR_IA32_CLK_MOD_ENABLE) {
		state = val & MSR_IA32_CLK_MOD_DUTY_CYCLE_MASK;
		state = state >> 1;
		thd_log_debug("current state  %x\n", state);
	}
コード例 #5
0
int cthd_topology::check_temperature(int index)
{
	ssize_t retval;
	char pathname[64];
	char temp_str[10];
	int fd;
	unsigned int temperature;
	int current_moving_average;

	if(index >= no_sensors)
		return 0;
	sprintf(pathname, "/sys/devices/platform/coretemp.0/temp%d_input", index);
	fd = open(pathname, O_RDONLY);
	if(fd < 0)
		return  - 1;
	retval = pread(fd, temp_str, sizeof(temp_str), 0);
	temperature = atoi(temp_str);

	current_moving_average = moving_average(temp_data, index, temperature);
	temp_data[index].last_moving_average = current_moving_average;

	thd_log_debug("DTS sensor %d mov average %u \n", index, current_moving_average)
	;
	close(fd);

	return temperature;
}
コード例 #6
0
void cthd_sysfs_cdev_rapl::set_curr_state_raw(int state, int arg) {
	std::stringstream state_str;
	std::stringstream tc_state_dev;
	int new_state;

	if (state <= min_state)
		new_state = phy_max;
	else {
		if (dynamic_phy_max_enable) {
			if (!calculate_phy_max()) {
				curr_state = state;
				return;
			}
		}
		new_state = phy_max - state;
	}
	curr_state = state;
	state_str << new_state;

	tc_state_dev << "constraint_" << constraint_index << "_power_limit_uw";
	if (cdev_sysfs.write(tc_state_dev.str(), state_str.str()) < 0)
		curr_state = (state == 0) ? 0 : max_state;

	thd_log_debug("set cdev state raw index %d state %d wr:%d\n", index, state,
			new_state);

}
コード例 #7
0
ファイル: thd_parse.cpp プロジェクト: poljar/thermal_daemon
bool cthd_parse::platform_matched()
{
	csys_fs thd_sysfs("/sys/class/dmi/id/");

	if (thd_sysfs.exists(std::string("product_uuid"))) {
		thd_log_debug("checking UUID\n");
		std::string str;
		if(thd_sysfs.read("product_uuid", str) >= 0) {
			thd_log_info("UUID is [%s]\n", str.c_str());
			for (unsigned int i=0; i<thermal_info_list.size(); ++i) {
				if (thermal_info_list[i].uuid == str) {
					matched_thermal_info_index = i;
					thd_log_info("Product UUID matched \n");
					return true;
				}
			}
		}
	}

	if (thd_sysfs.exists(std::string("product_name"))) {
		thd_log_debug("checking product name\n");
		char product_name[128];
		// Use different read method as the product name contains spaces
		if(thd_sysfs.read("product_name", product_name, 127) >= 0) {
			product_name[127] = '\0';
			int len = strlen(product_name);
			if (!len)
				return false;
			for (int i=0; i<len; ++i)
				if (product_name[i] == '\n')
					product_name[i] = '\0';
			thd_log_info("product name is[%s]\n", product_name);
			for (unsigned int i=0; i<thermal_info_list.size(); ++i) {
				if (!thermal_info_list[i].product_name.size())
					continue;
				if (thermal_info_list[i].product_name.compare(0, strlen(product_name), product_name) == 0) {
					matched_thermal_info_index = i;
					thd_log_info("Product Name matched \n");
					return true;
				}
			}
		}
	}

	return false;
}
コード例 #8
0
int cthd_cdev_rapl_msr::update()
{
	int ret;

	if (!rapl.pkg_domain_present())
		return THD_ERROR;

	if (!rapl.pp0_domain_present())
		return THD_ERROR;

	if (rapl.get_power_unit() < 0)
		return THD_ERROR;

	if (rapl.get_time_unit() < 0)
		return THD_ERROR;

	ret = rapl.get_pkg_power_info(&thermal_spec_power, &max_power, &min_power, &max_time_window);
	if (ret < 0)
		return ret;
	thd_log_debug("Pkg Power Info: Thermal spec %f watts, max %f watts, min %f watts, max time window %f seconds\n", thermal_spec_power, max_power, min_power, max_time_window);

	max_state = 0;

	if (thermal_spec_power > 0)
		phy_max = (int)thermal_spec_power * 1000; // change to milliwatts
	else if(max_power > 0)
		phy_max = (int)max_power * 1000; // // change to milliwatts
	else
		return THD_ERROR;

	set_inc_dec_value(phy_max * (float)rapl_power_dec_percent/100);

	if (inc_dec_val == 0)
		set_inc_dec_value(phy_max * (float)rapl_power_dec_percent*2/100);

	if (inc_dec_val == 0) // power limit is too small
		inc_dec_val = 1;


	max_state = phy_max - ((float)phy_max * rapl_low_limit_percent/100);

	thd_log_debug("RAPL phy_max %d max_state %d inc_dec %d \n", phy_max, max_state, inc_dec_val);

	return THD_SUCCESS;
}
コード例 #9
0
cthd_trip_point::cthd_trip_point(int _index, trip_point_type_t _type, unsigned
int _temp, unsigned int _hyst, int _zone_id, int _sensor_id,
		trip_control_type_t _control_type) :
		index(_index), type(_type), temp(_temp), hyst(_hyst), control_type(
				_control_type), zone_id(_zone_id), sensor_id(_sensor_id), trip_on(
				false), poll_on(false) {
	thd_log_debug("Add trip pt %d:%d:0x%x:%d:%d\n", type, zone_id, sensor_id,
			temp, hyst);
}
コード例 #10
0
ファイル: main.cpp プロジェクト: RAOF/thermal_daemon
// Callback function called to inform a sent value via dbus
gboolean thd_dbus_interface_set_current_preference(PrefObject *obj, gint
	*value_out, GError **error)
{
	int ret;
	thd_log_debug("thd_dbus_interface_set_current_preference %s\n", (char*)
	value_out);
	g_assert(obj != NULL);
	cthd_preference thd_pref;
	ret = thd_pref.set_preference((char*)value_out);
	thd_engine->send_message(PREF_CHANGED, 0, NULL);
}
コード例 #11
0
bool cthd_sysfs_cdev_rapl::calculate_phy_max() {
	if (dynamic_phy_max_enable) {
		unsigned int curr_max_phy;
		curr_max_phy = thd_engine->rapl_power_meter.rapl_action_get_power(
				PACKAGE);
		thd_log_debug("curr_phy_max = %u \n", curr_max_phy);
		if (curr_max_phy < rapl_min_default_step)
			return false;
		if (phy_max < curr_max_phy) {
			phy_max = curr_max_phy;
			set_inc_dec_value(phy_max * (float) rapl_power_dec_percent / 100);
			max_state = phy_max;
			max_state -= (float) max_state * rapl_low_limit_percent / 100;
			thd_log_debug("PHY_MAX %lu, step %d, max_state %d\n", phy_max,
					inc_dec_val, max_state);
		}
	}

	return true;
}
コード例 #12
0
ファイル: main.cpp プロジェクト: geeksville/thermal_daemon
// Callback function called to get value via dbus
gboolean thd_dbus_interface_get_current_preference(PrefObject *obj,
		gchar **pref_out, GError **error) {
	thd_log_debug("thd_dbus_interface_get_current_preference\n");
	g_assert(obj != NULL);
	gchar *value_out;
	static char *pref_str;

	pref_str = g_new(char, MAX_DBUS_REPLY_STR_LEN);

	if (!pref_str)
		return FALSE;

	cthd_preference thd_pref;
	value_out = (gchar*) thd_pref.get_preference_cstr();
	strncpy(pref_str, value_out, MAX_DBUS_REPLY_STR_LEN);
	thd_log_debug("thd_dbus_interface_get_current_preference out :%s\n",
			pref_str);
	*pref_out = pref_str;

	return TRUE;
}
コード例 #13
0
ファイル: main.cpp プロジェクト: geeksville/thermal_daemon
gboolean thd_dbus_interface_set_user_max_temperature(PrefObject *obj,
		gchar *zone_name, gchar *temperature, GError **error) {
	thd_log_debug("thd_dbus_interface_set_user_set_point %s:%s\n", zone_name,
			temperature);
	g_assert(obj != NULL);
	cthd_preference thd_pref;
	if (thd_engine->thd_engine_set_user_max_temp(zone_name,
			(char*) temperature) == THD_SUCCESS)
		thd_engine->send_message(PREF_CHANGED, 0, NULL);

	return TRUE;
}
コード例 #14
0
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;
}
コード例 #15
0
int cthd_cdev::thd_cdev_set_min_state(int zone_id) {
	zone_mask &= ~(1 << zone_id);
	if (zone_mask != 0) {
		thd_log_debug(
				"skip to reduce current state as this is controlled by two zone actions and one is still on %x\n",
				(unsigned int) zone_mask);
		return THD_SUCCESS;
	}
	trend_increase = false;
	set_curr_state(min_state, zone_id);

	return THD_SUCCESS;
}
コード例 #16
0
void cthd_zone::thermal_zone_temp_change(int id, unsigned int temp, int pref) {
	int i, count;
	bool updated_max = false;
	bool reset = false;

	count = trip_points.size();
	for (i = count - 1; i >= 0; --i) {
		cthd_trip_point &trip_point = trip_points[i];
		if (trip_point.get_trip_type() == MAX) {
			thd_model.add_sample(zone_temp);
			if (thd_model.is_set_point_reached()) {
				int set_point;
				set_point = thd_model.get_set_point();
				thd_log_debug("new set point %d \n", set_point);
				trip_point.thd_trip_update_set_point(set_point);
				updated_max = true;
			}
		}
		trip_point.thd_trip_point_check(id, temp, pref, &reset);
		// Force all cooling devices to min state
		if (reset) {
			zone_reset();
			break;
		}
	}
	// Re-adjust polling thresholds
	if (updated_max) {
		for (i = count - 1; i >= 0; --i) {
			cthd_trip_point &trip_point = trip_points[i];
			if (trip_point.get_trip_type() == POLLING) {
				thd_log_debug("new poll point %d \n",
						thd_model.get_hot_zone_trigger_point());
				trip_point.thd_trip_update_set_point(
						thd_model.get_hot_zone_trigger_point());
				trip_point.thd_trip_point_check(id, temp, pref, &reset);
			}
		}
	}
}
コード例 #17
0
unsigned int cthd_zone_dts_sensor::read_cpu_mask()
{
	std::stringstream filename;
	unsigned int mask = 0;

	filename << TDCONFDIR << "/" << "dts_" << index << "_sensor_mask.conf";
	thd_log_debug("read_cpu_mask file name %s\n", filename.str().c_str());
	std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
	if(ifs.good())
	{
		ifs >> mask;
		conf_present = true;
	}
コード例 #18
0
void cthd_trip_point::thd_trip_cdev_state_reset() {
	thd_log_info("thd_trip_cdev_state_reset \n");
	for (int i = cdevs.size() - 1; i >= 0; --i) {
		cthd_cdev *cdev = cdevs[i].cdev;
		thd_log_info("thd_trip_cdev_state_reset 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_min_state(zone_id);
	}
}
コード例 #19
0
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;
	}
}
コード例 #20
0
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;
}
コード例 #21
0
bool cthd_sysfs_cdev_rapl::read_ppcc_power_limits() {
	csys_fs sys_fs;

	if (sys_fs.exists("/sys/bus/pci/devices/0000:00:04.0/power_limits/"))
		sys_fs.update_path("/sys/bus/pci/devices/0000:00:04.0/power_limits/");
	else if (sys_fs.exists("/sys/bus/pci/devices/0000:00:0b.0/power_limits/"))
		sys_fs.update_path("/sys/bus/pci/devices/0000:00:0b.0/power_limits/");
	else if (sys_fs.exists(
			"/sys/bus/platform/devices/INT3401:00/power_limits/"))
		sys_fs.update_path(
				"/sys/bus/platform/devices/INT3401:00/power_limits/");
	else
		return false;

	if (sys_fs.exists("power_limit_0_max_uw")) {
		if (sys_fs.read("power_limit_0_max_uw", &pl0_max_pwr) <= 0)
			return false;
	}

	if (sys_fs.exists("power_limit_0_min_uw")) {
		if (sys_fs.read("power_limit_0_min_uw", &pl0_min_pwr) <= 0)
			return false;
	}

	if (sys_fs.exists("power_limit_0_tmin_us")) {
		if (sys_fs.read("power_limit_0_tmin_us", &pl0_min_window) <= 0)
			return false;
	}

	if (sys_fs.exists("power_limit_0_step_uw")) {
		if (sys_fs.read("power_limit_0_step_uw", &pl0_step_pwr) <= 0)
			return false;
	}

	if (pl0_max_pwr && pl0_min_pwr && pl0_min_window && pl0_step_pwr) {
		thd_log_debug("ppcc limits max:%u min:%u  min_win:%u step:%u\n",
				pl0_max_pwr, pl0_min_pwr, pl0_min_window, pl0_step_pwr);
		return true;
	}

	return false;
}
コード例 #22
0
bool cthd_preference::set_preference(const char *pref_str) {
    std::string str(pref_str);
    int pref = string_pref_to_int(str);

    std::stringstream filename;
    filename << TDRUNDIR << "/" << "thd_preference.conf";

    std::ofstream fout(filename.str().c_str());
    if (!fout.good()) {
        return false;
    }
    fout << pref;
    fout.close();

    // Save the old preference
    old_preference = preference;
    std::stringstream filename_save;
    filename_save << TDRUNDIR << "/" << "thd_preference.conf.save";

    std::ofstream fout_save(filename_save.str().c_str());
    if (!fout_save.good()) {
        return false;
    }
    fout_save << old_preference;
    fout_save.close();

    std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
    if (!ifs.good()) {
        preference = PREF_PERFORMANCE;
    } else {
        //ifs.read(reinterpret_cast < char * > (&preference), sizeof(preference));
        ifs >> preference;
    }
    ifs.close();

    thd_log_debug("old_preference %d new preference %d\n", old_preference,
                  preference);

    return true;
}
コード例 #23
0
void cthd_zone::update_zone_preference() {
	if (!zone_active)
		return;
	thd_log_debug("update_zone_preference\n");
	thd_model.update_user_set_max_temp();

	for (unsigned int i = 0; i < sensors.size(); ++i) {
		cthd_sensor *sensor;
		sensor = sensors[i];
		zone_temp = sensor->read_temperature();
		thermal_zone_temp_change(sensor->get_index(), 0,
				thd_engine->get_preference());
	}

	for (unsigned int i = 0; i < sensors.size(); ++i) {
		cthd_sensor *sensor;
		sensor = sensors[i];
		zone_temp = sensor->read_temperature();
		thermal_zone_temp_change(sensor->get_index(), zone_temp,
				thd_engine->get_preference());
	}
}
コード例 #24
0
int cthd_sysfs_cdev_rapl::update() {
	int i;
	std::stringstream temp_str;
	int _index = -1;
	unsigned long constraint_phy_max;
	bool ppcc = false;
	std::string domain_name;

	for (i = 0; i < rapl_no_time_windows; ++i) {
		temp_str << "constraint_" << i << "_name";
		if (cdev_sysfs.exists(temp_str.str())) {
			std::string type_str;
			cdev_sysfs.read(temp_str.str(), type_str);
			if (type_str == "long_term") {
				_index = i;
				break;
			}
		}
	}
	if (_index < 0) {
		thd_log_info("powercap RAPL no long term time window\n");
		return THD_ERROR;
	}

	cdev_sysfs.read("name", domain_name);
	if (domain_name == "package-0")
		ppcc = read_ppcc_power_limits();

	if (ppcc) {
		phy_max = pl0_max_pwr;
		set_inc_dec_value(pl0_step_pwr);
		max_state = pl0_max_pwr - pl0_min_pwr;
	} else {
		temp_str.str(std::string());
		temp_str << "constraint_" << _index << "_max_power_uw";
		if (!cdev_sysfs.exists(temp_str.str())) {
			thd_log_info("powercap RAPL no max power limit range %s \n",
					temp_str.str().c_str());
			return THD_ERROR;
		}
		if (cdev_sysfs.read(temp_str.str(), &phy_max) < 0) {
			thd_log_info("powercap RAPL invalid max power limit range \n");
			thd_log_info("Calculate dynamically phy_max \n");
			phy_max = 0;
			thd_engine->rapl_power_meter.rapl_start_measure_power();
			max_state = rapl_min_default_step;
			set_inc_dec_value(rapl_min_default_step);
			dynamic_phy_max_enable = true;
			return THD_SUCCESS;
		}

		std::stringstream temp_power_str;
		temp_power_str.str(std::string());
		temp_power_str << "constraint_" << _index << "_power_limit_uw";
		if (!cdev_sysfs.exists(temp_power_str.str())) {
			thd_log_info("powercap RAPL no  power limit uw %s \n",
					temp_str.str().c_str());
			return THD_ERROR;
		}
		if (cdev_sysfs.read(temp_power_str.str(), &constraint_phy_max) <= 0) {
			thd_log_info("powercap RAPL invalid max power limit range \n");
			constraint_phy_max = 0;
		}
		if (constraint_phy_max > phy_max) {
			thd_log_info(
					"Default constraint power limit is more than max power %lu:%lu\n",
					constraint_phy_max, phy_max);
			phy_max = constraint_phy_max;
		}
		thd_log_info("powercap RAPL max power limit range %lu \n", phy_max);

		set_inc_dec_value(phy_max * (float) rapl_power_dec_percent / 100);
		max_state = phy_max;
		max_state -= (float) max_state * rapl_low_limit_percent / 100;
	}
	std::stringstream time_window;
	temp_str.str(std::string());
	temp_str << "constraint_" << _index << "_time_window_us";
	if (!cdev_sysfs.exists(temp_str.str())) {
		thd_log_info("powercap RAPL no time_window_us %s \n",
				temp_str.str().c_str());
		return THD_ERROR;
	}
	if (pl0_min_window)
		time_window << pl0_min_window;
	else
		time_window << def_rapl_time_window;
	cdev_sysfs.write(temp_str.str(), time_window.str());

	std::stringstream enable;
	temp_str.str(std::string());
	temp_str << "enabled";
	if (!cdev_sysfs.exists(temp_str.str())) {
		thd_log_info("powercap RAPL no enabled %s \n", temp_str.str().c_str());
		return THD_ERROR;
	}
	cdev_sysfs.write(temp_str.str(), "0");

	thd_log_debug("RAPL max limit %d increment: %d\n", max_state, inc_dec_val);
	constraint_index = _index;
	set_pid_param(1000, 100, 10);

	return THD_SUCCESS;
}
コード例 #25
0
ファイル: main.cpp プロジェクト: geeksville/thermal_daemon
// 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;
}
コード例 #26
0
int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp,
		int temperature, int state, int zone_id) {

	curr_state = get_curr_state();
	if ((min_state < max_state && curr_state < min_state)
			|| (min_state > max_state && curr_state > min_state))
		curr_state = min_state;
	max_state = get_max_state();
	thd_log_debug("thd_cdev_set_%d:curr state %d max state %d\n", index,
			curr_state, max_state);
	if (state) {
		if ((min_state < max_state && curr_state < max_state)
				|| (min_state > max_state && curr_state > max_state)) {
			int state = curr_state + inc_dec_val;
			if (trend_increase) {
				if (curr_pow == 0)
					base_pow_state = curr_state;
				++curr_pow;
				state = base_pow_state + int_2_pow(curr_pow) * inc_dec_val;
				thd_log_info(
						"cdev index:%d consecutive call, increment exponentially state %d\n",
						index, state);
				if ((min_state < max_state && state >= max_state)
						|| (min_state > max_state && state <= max_state)) {
					state = max_state;
					curr_pow = 0;
					curr_state = max_state;
				}
			} else {
				curr_pow = 0;
			}
			trend_increase = true;
			if ((min_state < max_state && state > max_state)
					|| (min_state > max_state && state < max_state))
				state = max_state;
			thd_log_debug("op->device:%s %d\n", type_str.c_str(), state);
			set_curr_state(state, zone_id);
		}
	} else {
		curr_pow = 0;
		trend_increase = false;
		if (((min_state < max_state && curr_state > min_state)
				|| (min_state > max_state && curr_state < min_state))
				&& auto_down_adjust == false) {
			int state = curr_state - inc_dec_val;
			if ((min_state < max_state && state < min_state)
					|| (min_state > max_state && state > min_state))
				state = min_state;
			thd_log_debug("op->device:%s %d\n", type_str.c_str(), state);
			set_curr_state(state, zone_id);
		} else {
			thd_log_debug("op->device: force min %s %d\n", type_str.c_str(),
					min_state);
			set_curr_state(min_state, zone_id);
		}
	}

	thd_log_info(
			"Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n",
			set_point, temperature, index, type_str.c_str(), get_curr_state(),
			max_state);

	thd_log_debug("<<thd_cdev_set_state %d\n", state);

	return THD_SUCCESS;
}
コード例 #27
0
bool cthd_rapl_power_meter::rapl_energy_loop() {
	csys_fs sys_fs;
	int status;
	unsigned long long counter;
	unsigned long long diff;
	time_t curr_time;

	if (!enable_measurement)
		return false;

	curr_time = time(NULL);
	if ((curr_time - last_time) <= 0)
		return true;
	for (unsigned int i = 0; i < domain_list.size(); ++i) {
		std::string buffer;
		std::string path;

		if (!domain_list[i].max_energy_range) {
			std::string _path;
			std::string _buffer;
			_path = domain_list[i].path + "/" + "max_energy_range_uj";
			status = sys_fs.read(_path, _buffer);
			if (status >= 0)
				domain_list[i].max_energy_range = atoll(_buffer.c_str()) / 1000;
			domain_list[i].max_energy_range_threshold =
					domain_list[i].max_energy_range / 2;
		}

		path = domain_list[i].path + "/" + "energy_uj";
		status = sys_fs.read(path, buffer);
		if (status >= 0) {
			counter = domain_list[i].energy_counter;
			domain_list[i].energy_counter = atoll(buffer.c_str()) / 1000; // To milli Js

			diff = 0;
			if (domain_list[i].half_way
					&& domain_list[i].energy_counter
							< domain_list[i].max_energy_range_threshold) {
				// wrap around
				domain_list[i].energy_cumulative_counter +=
						domain_list[i].max_energy_range;
				diff = domain_list[i].max_energy_range - counter;
				counter = 0;
				domain_list[i].half_way = 0;

			} else if (domain_list[i].energy_counter
					> domain_list[i].max_energy_range_threshold)
				domain_list[i].half_way = 1;

			if (counter)
				domain_list[i].power = (domain_list[i].energy_counter - counter
						+ diff) / (curr_time - last_time);
			if (domain_list[i].power > domain_list[i].max_power)
				domain_list[i].max_power = domain_list[i].power;

			if (domain_list[i].min_power == 0)
				domain_list[i].min_power = domain_list[i].power;
			else if (domain_list[i].power < domain_list[i].min_power)
				domain_list[i].min_power = domain_list[i].power;

			thd_log_debug(" energy %d:%lld:%lld mj: %u mw \n",
					domain_list[i].type,
					domain_list[i].energy_cumulative_counter,
					domain_list[i].energy_counter
							+ domain_list[i].energy_cumulative_counter,
					domain_list[i].power);

		}
	}
	last_time = curr_time;

	return true;
}
コード例 #28
0
cthd_zone::cthd_zone(int _index, std::string control_path, sensor_relate_t rel) :
		index(_index), zone_sysfs(control_path.c_str()), zone_temp(0), zone_active(
				false), zone_cdev_binded_status(false), type_str(), sensor_rel(
				rel), thd_model("") {
	thd_log_debug("Added zone index:%d \n", index);
}
コード例 #29
0
int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp,
		int temperature, int state, int zone_id, int trip_id,
		int target_value) {

	time_t tm;
	int ret;

	time(&tm);
	thd_log_debug(">>thd_cdev_set_state index:%d state:%d :%d:%d:%d\n", index,
			state, zone_id, trip_id, target_value);
	if (last_state == state && (tm - last_action_time) <= debounce_interval) {
		thd_log_debug(
				"Ignore: delay < debounce interval : %d, %d, %d, %d, %d\n",
				set_point, temperature, index, get_curr_state(), max_state);
		return THD_SUCCESS;
	}
	last_state = state;
	if (state) {
		zone_mask |= (1 << zone_id);
		trip_mask |= (1 << trip_id);

		if (target_value != TRIP_PT_INVALID_TARGET_STATE) {
			zone_trip_limits_t limit;
			bool found = false;

			for (unsigned int i = 0; i < zone_trip_limits.size(); ++i) {
				if (zone_trip_limits[i].zone == zone_id
						&& zone_trip_limits[i].trip == trip_id) {
					found = true;
					break;
				}
			}
			if (!found) {
				limit.zone = zone_id;
				limit.trip = trip_id;
				limit.target_value = target_value;
				thd_log_debug("Added zone %d trip %d clamp %d\n", limit.zone,
						limit.trip, limit.target_value);
				zone_trip_limits.push_back(limit);
				std::sort(zone_trip_limits.begin(), zone_trip_limits.end(),
						sort_clamp_values);
			}
			set_curr_state_raw(target_value, zone_id);
			curr_state = target_value;
			last_action_time = tm;
			thd_log_info(
					"Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n",
					set_point, temperature, index, type_str.c_str(),
					get_curr_state(), max_state);
			return THD_SUCCESS;
		}
	} else {

		if (zone_mask & (1 << zone_id)) {
			if (trip_mask & (1 << trip_id)) {
				trip_mask &= ~(1 << trip_id);
				zone_mask &= ~(1 << zone_id);
			}
		}

		if (zone_trip_limits.size() > 0) {
			int length = zone_trip_limits.size();
			int i;

			// Just remove the current zone requesting to turn off
			for (i = 0; i < length; ++i) {
				if (zone_trip_limits[i].zone == zone_id
						&& zone_trip_limits[i].trip == trip_id) {
					zone_trip_limits.erase(zone_trip_limits.begin() + i);
					thd_log_debug("Erased  [%d: %d\n", zone_id, trip_id);
					break;
				}
			}
			zone_trip_limits_t limit;

			if (zone_trip_limits.size() == 0) {
				limit.target_value = get_min_state();
				limit.zone = zone_id;
				limit.trip = trip_id;
			} else {
				limit = zone_trip_limits[zone_trip_limits.size() - 1];
			}

			if (cmp_current_state(limit.target_value) < 0) {
				thd_log_info(
						"new active zone; next in line  %d trip %d clamp %d\n",
						limit.zone, limit.trip, limit.target_value);
				set_curr_state_raw(limit.target_value, zone_id);
				thd_log_info(
						"Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n",
						set_point, temperature, index, type_str.c_str(),
						get_curr_state(), max_state);
			}
			return THD_SUCCESS;

		} else if (zone_mask != 0 || trip_mask != 0) {
			thd_log_debug(
					"skip to reduce current state as this is controlled by two zone or trip actions and one is still on %lx:%lx\n",
					zone_mask, trip_mask);
			return THD_SUCCESS;
		}
	}
	last_action_time = tm;

	curr_state = get_curr_state();
	if (curr_state == get_min_state()) {
		control_begin();
	}
	if (pid_enable) {
		pid_ctrl.set_target_temp(target_temp);
		ret = pid_ctrl.pid_output(temperature);
		ret += get_curr_state();
		if (ret > get_max_state())
			ret = get_max_state();
		if (ret < get_min_state())
			ret = get_min_state();
		set_curr_state_raw(ret, zone_id);
		thd_log_debug("Set : %d, %d, %d, %d, %d\n", set_point, temperature,
				index, get_curr_state(), max_state);
		ret = THD_SUCCESS;
	} else {
		ret = thd_cdev_exponential_controller(set_point, target_temp,
				temperature, state, zone_id);
	}
	if (curr_state == get_max_state()) {
		control_end();
	}

	return ret;
}
コード例 #30
0
void cthd_rapl_power_meter::rapl_read_domains(const char *dir_name) {
	int count = 0;
	csys_fs sys_fs;

	if (rapl_present) {
		DIR *dir;
		struct dirent *dir_entry;
		thd_log_debug("RAPL base path %s\n", dir_name);
		if ((dir = opendir(dir_name)) != NULL) {
			while ((dir_entry = readdir(dir)) != NULL) {
				std::string buffer;
				std::stringstream path;
				int status;
				rapl_domain_t domain;

				domain.half_way = 0;
				domain.energy_counter = 0;
				domain.energy_cumulative_counter = 0;
				domain.max_energy_range = 0;
				domain.max_energy_range_threshold = 0;
				domain.power = 0;
				domain.max_power = 0;
				domain.min_power = 0;
				domain.type = PACKAGE;

				if (!strcmp(dir_entry->d_name, ".")
						|| !strcmp(dir_entry->d_name, ".."))
					continue;
				thd_log_debug("RAPL domain dir %s\n", dir_entry->d_name);
				path << dir_name << dir_entry->d_name << "/" << "name";
				if (!sys_fs.exists(path.str())) {
					thd_log_debug(" %s doesn't exist\n", path.str().c_str());
					continue;
				}
				status = sys_fs.read(path.str(), buffer);
				if (status < 0)
					continue;
				thd_log_debug("name %s\n", buffer.c_str());
				if (fnmatch("package-*", buffer.c_str(), 0) == 0) {
					domain.type = PACKAGE;
					std::stringstream path;
					path << dir_name << dir_entry->d_name << "/";
					rapl_read_domains(path.str().c_str());
				} else if (buffer == "core") {
					domain.type = CORE;
				} else if (buffer == "uncore") {
					domain.type = UNCORE;
				} else if (buffer == "dram") {
					domain.type = DRAM;
				}
				if (measure_mask & domain.type) {
					domain.name = buffer;
					domain.path = std::string(dir_name)
							+ std::string(dir_entry->d_name);
					domain_list.push_back(domain);
					++count;
				}
			}
			closedir(dir);
		} else {
			thd_log_debug("opendir failed %s :%s\n", strerror(errno),
					rapl_sysfs.get_base_path());
		}
	}

	thd_log_info("RAPL domain count %d\n", count);
}