Commit 5783ecc9 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-tools'

Merge cpupower utility fixes for 6.4-rc3:

 - Read TSC on each CPU right before reading MPERF so as to reduce the
   potential time difference between the TSC and MPERF accesses and
   improve the C0 percentage calculation (Wyes Karny).

 - Fix a possible file handle leak and clean up the code in
   sysfs_get_enabled() (Hao Zeng).

* pm-tools:
  cpupower: Make TSC read per CPU for Mperf monitor
  cpupower:Fix resource leaks in sysfs_get_enabled()
parents 73c7f824 eab866bf
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -40,25 +40,34 @@ static int sysfs_get_enabled(char *path, int *mode)
{
	int fd;
	char yes_no;
	int ret = 0;

	*mode = 0;

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;
	if (fd == -1) {
		ret = -1;
		goto out;
	}

	if (read(fd, &yes_no, 1) != 1) {
		close(fd);
		return -1;
		ret = -1;
		goto out_close;
	}

	if (yes_no == '1') {
		*mode = 1;
		return 0;
		goto out_close;
	} else if (yes_no == '0') {
		return 0;
		goto out_close;
	} else {
		ret = -1;
		goto out_close;
	}
	return -1;
out_close:
	close(fd);
out:
	return ret;
}

int powercap_get_enabled(int *mode)
+14 −17
Original line number Diff line number Diff line
@@ -70,8 +70,8 @@ static int max_freq_mode;
 */
static unsigned long max_frequency;

static unsigned long long tsc_at_measure_start;
static unsigned long long tsc_at_measure_end;
static unsigned long long *tsc_at_measure_start;
static unsigned long long *tsc_at_measure_end;
static unsigned long long *mperf_previous_count;
static unsigned long long *aperf_previous_count;
static unsigned long long *mperf_current_count;
@@ -169,7 +169,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
	aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];

	if (max_freq_mode == MAX_FREQ_TSC_REF) {
		tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
		tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
		*percent = 100.0 * mperf_diff / tsc_diff;
		dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
		       mperf_cstates[id].name, mperf_diff, tsc_diff);
@@ -206,7 +206,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,

	if (max_freq_mode == MAX_FREQ_TSC_REF) {
		/* Calculate max_freq from TSC count */
		tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
		tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
		time_diff = timespec_diff_us(time_start, time_end);
		max_frequency = tsc_diff / time_diff;
	}
@@ -225,33 +225,27 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
static int mperf_start(void)
{
	int cpu;
	unsigned long long dbg;

	clock_gettime(CLOCK_REALTIME, &time_start);
	mperf_get_tsc(&tsc_at_measure_start);

	for (cpu = 0; cpu < cpu_count; cpu++)
	for (cpu = 0; cpu < cpu_count; cpu++) {
		mperf_get_tsc(&tsc_at_measure_start[cpu]);
		mperf_init_stats(cpu);
	}

	mperf_get_tsc(&dbg);
	dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
	return 0;
}

static int mperf_stop(void)
{
	unsigned long long dbg;
	int cpu;

	for (cpu = 0; cpu < cpu_count; cpu++)
	for (cpu = 0; cpu < cpu_count; cpu++) {
		mperf_measure_stats(cpu);
		mperf_get_tsc(&tsc_at_measure_end[cpu]);
	}

	mperf_get_tsc(&tsc_at_measure_end);
	clock_gettime(CLOCK_REALTIME, &time_end);

	mperf_get_tsc(&dbg);
	dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);

	return 0;
}

@@ -353,7 +347,8 @@ struct cpuidle_monitor *mperf_register(void)
	aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
	mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
	aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));

	tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
	tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
	mperf_monitor.name_len = strlen(mperf_monitor.name);
	return &mperf_monitor;
}
@@ -364,6 +359,8 @@ void mperf_unregister(void)
	free(aperf_previous_count);
	free(mperf_current_count);
	free(aperf_current_count);
	free(tsc_at_measure_start);
	free(tsc_at_measure_end);
	free(is_valid);
}