From fac783d18d61af232b957af259a15ed231f6869b Mon Sep 17 00:00:00 2001
From: Juliet Kim <julietk@linux.vnet.ibm.com>
Date: Thu, 13 Sep 2018 15:57:42 -0400
Subject: [PATCH] ppc64_cpu: Limit number of CPUs for frequency calculation

The patch limits the number of threads used for CPU frequency calculation
to the minimum of either the actual number of CPUs in the system or
CPU_SETSIZE(currently 1024). In other words, if the number of CPUs in the
system is less than CPU_SETSIZE, a thread is created for each of the CPUs,
otherwise only CPU_SETSIZE threads are created. This is being done because
sched_setaffinity() will only work on CPU_SETSIZE CPUs, anything over the
limit is not supported.

Signed-off-by: Juliet Kim <julietk@linux.vnet.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
---
 src/ppc64_cpu.c | 43 +++++++++++++++++++++++++------------------
 1 file changed, 25 insertions(+), 18 deletions(-)

Index: powerpc-utils-1.3.4/src/ppc64_cpu.c
===================================================================
--- powerpc-utils-1.3.4.orig/src/ppc64_cpu.c
+++ powerpc-utils-1.3.4/src/ppc64_cpu.c
@@ -35,6 +35,7 @@
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
+#include <sys/param.h>
 
 #ifdef WITH_LIBRTAS
 #include <librtas.h>
@@ -849,7 +850,7 @@ static int do_run_mode(char *run_mode)
 
 #ifdef HAVE_LINUX_PERF_EVENT_H
 
-static int setup_counters(struct cpu_freq *cpu_freqs)
+static int setup_counters(struct cpu_freq *cpu_freqs, int max_thread)
 {
 	int i;
 	struct perf_event_attr attr;
@@ -860,7 +861,7 @@ static int setup_counters(struct cpu_fre
 	attr.disabled = 1;
 	attr.size = sizeof(attr);
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		if (!cpu_online(i)) {
 			cpu_freqs[i].offline = 1;
 			continue;
@@ -883,11 +884,11 @@ static int setup_counters(struct cpu_fre
 	return 0;
 }
 
-static void start_counters(struct cpu_freq *cpu_freqs)
+static void start_counters(struct cpu_freq *cpu_freqs, int max_thread)
 {
 	int i;
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		if (cpu_freqs[i].offline)
 			continue;
 
@@ -895,11 +896,11 @@ static void start_counters(struct cpu_fr
 	}
 }
 
-static void stop_counters(struct cpu_freq *cpu_freqs)
+static void stop_counters(struct cpu_freq *cpu_freqs, int max_thread)
 {
 	int i;
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		if (cpu_freqs[i].offline)
 			continue;
 
@@ -907,11 +908,11 @@ static void stop_counters(struct cpu_fre
 	}
 }
 
-static void read_counters(struct cpu_freq *cpu_freqs)
+static void read_counters(struct cpu_freq *cpu_freqs, int max_thread)
 {
 	int i;
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		size_t res;
 
 		if (cpu_freqs[i].offline)
@@ -925,11 +926,11 @@ static void read_counters(struct cpu_fre
 	}
 }
 
-static void check_threads(struct cpu_freq *cpu_freqs)
+static void check_threads(struct cpu_freq *cpu_freqs, int max_thread)
 {
 	int i;
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		if (cpu_freqs[i].offline)
 			continue;
 
@@ -1060,21 +1061,27 @@ static int do_cpu_frequency(int sleep_ti
 	unsigned long long sum = 0;
 	unsigned long count = 0;
 	struct cpu_freq *cpu_freqs;
+	int max_thread;
 
 	setrlimit_open_files();
 
-	cpu_freqs = calloc(threads_in_system, sizeof(*cpu_freqs));
+	max_thread = MIN(threads_in_system, CPU_SETSIZE);
+	if (max_thread < threads_in_system)
+		printf("ppc64_cpu currently supports up to %d CPUs\n",
+			CPU_SETSIZE);
+
+	cpu_freqs = calloc(max_thread, sizeof(*cpu_freqs));
 	if (!cpu_freqs)
 		return -ENOMEM;
 
-	rc = setup_counters(cpu_freqs);
+	rc = setup_counters(cpu_freqs, max_thread);
 	if (rc) {
 		free(cpu_freqs);
 		return rc;
 	}
 
 	/* Start a soak thread on each CPU */
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		if (cpu_freqs[i].offline)
 			continue;
 
@@ -1089,15 +1096,15 @@ static int do_cpu_frequency(int sleep_ti
 	/* Wait for soak threads to start */
 	usleep(1000000);
 
-	start_counters(cpu_freqs);
+	start_counters(cpu_freqs, max_thread);
 	/* Count for specified timeout in seconds */
 	usleep(sleep_time * 1000000);
 
-	stop_counters(cpu_freqs);
-	check_threads(cpu_freqs);
-	read_counters(cpu_freqs);
+	stop_counters(cpu_freqs, max_thread);
+	check_threads(cpu_freqs, max_thread);
+	read_counters(cpu_freqs, max_thread);
 
-	for (i = 0; i < threads_in_system; i++) {
+	for (i = 0; i < max_thread; i++) {
 		unsigned long long frequency;
 
 		if (cpu_freqs[i].offline)
