Blame SOURCES/powerpc-utils-149c7022a56e0ffb5fe27681f574d46860323e3c.patch

956c23
commit 149c7022a56e0ffb5fe27681f574d46860323e3c
956c23
Author: Anton Blanchard <anton.blanchard@gmail.com>
956c23
Date:   Sun Oct 8 21:49:17 2017 -0700
956c23
956c23
    ppc64_cpu: Scale CPU cycles counter by amount of time it ran
956c23
    
956c23
    ------=_Part_8274_1145520959.1507524557284
956c23
    Content-Type: text/plain; charset="UTF-8"
956c23
    
956c23
    At the moment we start a CPU cycles counter, sleep one second and
956c23
    read the counter value, assuming we got one second of time on the
956c23
    PMU.
956c23
    
956c23
    There are two issues with this. If someone else is consuming all
956c23
    the available PMCs, we may end up context switching the PMC and
956c23
    count for half (or less) of the time. In this case we report a CPU
956c23
    frequency that is half (or less) of what it should be.
956c23
    
956c23
    On the other hand if the sleep goes for longer than one second which
956c23
    might happen on a busy box, then we count for too long and report a
956c23
    CPU frequency that is too high.
956c23
    
956c23
    Also check that we got a reasonable number of cycles and report
956c23
    an error if we did not.
956c23
    
956c23
    Signed-off-by: Anton Blanchard <anton@samba.org>
956c23
    
956c23
    --
956c23
    You received this message because you are subscribed to the Google Groups "Powerpc-utils development mailing list" group.
956c23
    To unsubscribe from this group and stop receiving emails from it, send an email to powerpc-utils-devel+unsubscribe@googlegroups.com.
956c23
    To post to this group, send email to powerpc-utils-devel@googlegroups.com.
956c23
    To view this discussion on the web visit https://groups.google.com/d/msgid/powerpc-utils-devel/6f7e063a-0e51-48fa-a1ae-07b06d3ab8ad%40googlegroups.com.
956c23
    For more options, visit https://groups.google.com/d/optout.
956c23
    
956c23
    
At the moment we start a CPU cycles counter, sleep one second and
read the counter value, assuming we got one second of time on the
PMU.

There are two issues with this. If someone else is consuming all
the available PMCs, we may end up context switching the PMC and
count for half (or less) of the time. In this case we report a CPU
frequency that is half (or less) of what it should be.

On the other hand if the sleep goes for longer than one second which
might happen on a busy box, then we count for too long and report a
CPU frequency that is too high.

Also check that we got a reasonable number of cycles and report
an error if we did not.

Signed-off-by: Anton Blanchard <anton@samba.org>

956c23
    
956c23
    

956c23
    
956c23
    -- 
956c23
    You received this message because you are subscribed to the Google Groups "Powerpc-utils development mailing list" group.
956c23
    To unsubscribe from this group and stop receiving emails from it, send an email to powerpc-utils-devel+unsubscribe@googlegroups.com.
956c23
    To post to this group, send email to powerpc-utils-devel@googlegroups.com.
956c23
    To view this discussion on the web visit https://groups.google.com/d/msgid/powerpc-utils-devel/6f7e063a-0e51-48fa-a1ae-07b06d3ab8ad%40googlegroups.com.
956c23
    For more options, visit https://groups.google.com/d/optout.
956c23
    Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
956c23
956c23
diff --git a/src/ppc64_cpu.c b/src/ppc64_cpu.c
956c23
index 87840df..34654b4 100644
956c23
--- a/src/ppc64_cpu.c
956c23
+++ b/src/ppc64_cpu.c
956c23
@@ -64,7 +64,7 @@ struct cpu_freq {
956c23
 	int offline;
956c23
 	int counter;
956c23
 	pthread_t tid;
956c23
-	unsigned long long freq;
956c23
+	double freq;
956c23
 };
956c23
 
956c23
 #ifndef __NR_perf_event_open
956c23
@@ -860,6 +860,9 @@ static int setup_counters(struct cpu_freq *cpu_freqs)
956c23
 	attr.disabled = 1;
956c23
 	attr.size = sizeof(attr);
956c23
 
956c23
+	/* Record how long the event ran for */
956c23
+	attr.read_format |= PERF_FORMAT_TOTAL_TIME_RUNNING;
956c23
+
956c23
 	for (i = 0; i < threads_in_system; i++) {
956c23
 		if (!cpu_online(i)) {
956c23
 			cpu_freqs[i].offline = 1;
956c23
@@ -907,9 +910,15 @@ static void stop_counters(struct cpu_freq *cpu_freqs)
956c23
 	}
956c23
 }
956c23
 
956c23
+struct read_format {
956c23
+	uint64_t value;
956c23
+	uint64_t time_running;
956c23
+};
956c23
+
956c23
 static void read_counters(struct cpu_freq *cpu_freqs)
956c23
 {
956c23
 	int i;
956c23
+	struct read_format vals;
956c23
 
956c23
 	for (i = 0; i < threads_in_system; i++) {
956c23
 		size_t res;
956c23
@@ -917,9 +926,16 @@ static void read_counters(struct cpu_freq *cpu_freqs)
956c23
 		if (cpu_freqs[i].offline)
956c23
 			continue;
956c23
 
956c23
-		res = read(cpu_freqs[i].counter, &cpu_freqs[i].freq,
956c23
-			   sizeof(unsigned long long));
956c23
-		assert(res == sizeof(unsigned long long));
956c23
+		res = read(cpu_freqs[i].counter, &vals, sizeof(vals));
956c23
+		assert(res == sizeof(vals));
956c23
+
956c23
+		/* Warn if we don't get at least 0.1s of time on the CPU */
956c23
+		if (vals.time_running < 100000000) {
956c23
+			fprintf(stderr, "Measurement interval was too small, is someone running perf?\n");
956c23
+			exit(1);
956c23
+		}
956c23
+
956c23
+		cpu_freqs[i].freq = 1.0 * vals.value / vals.time_running;
956c23
 
956c23
 		close(cpu_freqs[i].counter);
956c23
 	}
956c23
@@ -1048,16 +1064,14 @@ static void setrlimit_open_files(void)
956c23
 	setrlimit(RLIMIT_NOFILE, &new_rlim);
956c23
 }
956c23
 
956c23
-#define freq_calc(cycles, time)	(1.0 * (cycles) / (time) / 1000000000ULL)
956c23
-
956c23
 static int do_cpu_frequency(int sleep_time)
956c23
 {
956c23
 	int i, rc;
956c23
-	unsigned long long min = -1ULL;
956c23
+	double min = -1ULL;
956c23
 	unsigned long min_cpu = -1UL;
956c23
-	unsigned long long max = 0;
956c23
+	double max = 0;
956c23
 	unsigned long max_cpu = -1UL;
956c23
-	unsigned long long sum = 0;
956c23
+	double sum = 0;
956c23
 	unsigned long count = 0;
956c23
 	struct cpu_freq *cpu_freqs;
956c23
 
956c23
@@ -1098,7 +1112,7 @@ static int do_cpu_frequency(int sleep_time)
956c23
 	read_counters(cpu_freqs);
956c23
 
956c23
 	for (i = 0; i < threads_in_system; i++) {
956c23
-		unsigned long long frequency;
956c23
+		double frequency;
956c23
 
956c23
 		if (cpu_freqs[i].offline)
956c23
 			continue;
956c23
@@ -1118,11 +1132,9 @@ static int do_cpu_frequency(int sleep_time)
956c23
 	}
956c23
 
956c23
 	report_system_power_mode();
956c23
-	printf("min:\t%.3f GHz (cpu %ld)\n", freq_calc(min, sleep_time),
956c23
-	       min_cpu);
956c23
-	printf("max:\t%.3f GHz (cpu %ld)\n", freq_calc(max, sleep_time),
956c23
-	       max_cpu);
956c23
-	printf("avg:\t%.3f GHz\n\n", freq_calc((sum / count), sleep_time));
956c23
+	printf("min:\t%.3f GHz (cpu %ld)\n", min, min_cpu);
956c23
+	printf("max:\t%.3f GHz (cpu %ld)\n", max, max_cpu);
956c23
+	printf("avg:\t%.3f GHz\n\n", sum / count);
956c23
 
956c23
 	free(cpu_freqs);
956c23
 	return 0;