From: Tony Jones <tonyj@suse.de>
Patch-mainline: pending for tip
References: bnc#585238
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git#perf-core
Date: Mon March 29 2010
Subject: perf tools: Dynamically allocate arrays based on #configured cpus
Signed-Off-By: Tony Jones <tonyj@suse.de>

This patch increases MAX_NR_CPUS to 4096 (matching tip tree) but makes the
actual size of allocate dependant on the number of configured cpus. A different
version of this patch (due to -t tid changes) is upstream.

---
 tools/perf/builtin-record.c |   15 +++++++++++----
 tools/perf/builtin-stat.c   |    6 +++++-
 tools/perf/builtin-top.c    |   12 +++++++++---
 tools/perf/perf.h           |    2 +-
 4 files changed, 26 insertions(+), 9 deletions(-)

--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -26,7 +26,7 @@
 #define ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a)-1)
 #define __ALIGN_MASK(x, mask)	(((x)+(mask))&~(mask))
 
-static int			fd[MAX_NR_CPUS][MAX_COUNTERS];
+static int			(*fd)[MAX_COUNTERS];
 
 static long			default_interval		= 100000;
 
@@ -59,7 +59,7 @@ static struct timeval		this_read;
 
 static u64			bytes_written;
 
-static struct pollfd		event_array[MAX_NR_CPUS * MAX_COUNTERS];
+static struct pollfd		*event_array;
 
 static int			nr_poll;
 static int			nr_cpu;
@@ -75,7 +75,7 @@ struct mmap_data {
 	unsigned int		prev;
 };
 
-static struct mmap_data		mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
+static struct mmap_data		(*mmap_array)[MAX_COUNTERS];
 
 static unsigned long mmap_read_head(struct mmap_data *md)
 {
@@ -537,6 +537,14 @@ static int __cmd_record(int argc, const
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 
+	nr_cpus = (system_wide && profile_cpu == -1) ? read_cpu_map() : 1;
+
+	fd = calloc(nr_cpus * MAX_COUNTERS, sizeof(int));
+	event_array = calloc(nr_cpus * MAX_COUNTERS, sizeof(struct pollfd));
+	mmap_array = calloc(nr_cpus * MAX_COUNTERS, sizeof(struct mmap_data));
+	if (!fd || !event_array || !mmap_array)
+		return -ENOMEM;
+
 	if (!stat(output_name, &st) && st.st_size) {
 		if (!force && !append_file) {
 			fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
@@ -587,7 +595,6 @@ static int __cmd_record(int argc, const
 		if (profile_cpu != -1) {
 			open_counters(profile_cpu, target_pid);
 		} else {
-			nr_cpus = read_cpu_map();
 			for (i = 0; i < nr_cpus; i++)
 				open_counters(cpumap[i], target_pid);
 		}
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -74,7 +74,7 @@ static pid_t			target_pid			= -1;
 static pid_t			child_pid			= -1;
 static int			null_run			=  0;
 
-static int			fd[MAX_NR_CPUS][MAX_COUNTERS];
+static int			(*fd)[MAX_COUNTERS];
 
 static int			event_scaled[MAX_COUNTERS];
 
@@ -495,6 +495,10 @@ int cmd_stat(int argc, const char **argv
 	else
 		nr_cpus = 1;
 
+	fd = calloc(nr_cpus * MAX_COUNTERS, sizeof(int));
+	if (!fd)
+		return -ENOMEM;
+
 	/*
 	 * We dont want to block the signals - that would cause
 	 * child tasks to inherit that and Ctrl-C would not work.
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -53,7 +53,7 @@
 #include <linux/unistd.h>
 #include <linux/types.h>
 
-static int			fd[MAX_NR_CPUS][MAX_COUNTERS];
+static int			(*fd)[MAX_COUNTERS];
 
 static int			system_wide			=  0;
 
@@ -991,8 +991,8 @@ static void mmap_read_counter(struct mma
 	md->prev = old;
 }
 
-static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
-static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
+static struct pollfd *event_array;
+static struct mmap_data (*mmap_array)[MAX_COUNTERS];
 
 static void mmap_read(void)
 {
@@ -1210,5 +1210,11 @@ int cmd_top(int argc, const char **argv,
 	else
 		nr_cpus = read_cpu_map();
 
+	fd = calloc(nr_cpus * MAX_COUNTERS, sizeof(int));
+	event_array = calloc(nr_cpus * MAX_COUNTERS, sizeof(struct pollfd));
+	mmap_array = calloc(nr_cpus * MAX_COUNTERS, sizeof(struct mmap_data));
+	if (!fd || !event_array || !mmap_array)
+		 return -ENOMEM;
+
 	return __cmd_top();
 }
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -100,7 +100,7 @@ sys_perf_event_open(struct perf_event_at
 }
 
 #define MAX_COUNTERS			256
-#define MAX_NR_CPUS			256
+#define MAX_NR_CPUS			4096
 
 struct ip_callchain {
 	u64 nr;
