aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-record.c14
-rw-r--r--tools/perf/builtin-stat.c36
-rw-r--r--tools/perf/builtin-top.c22
-rw-r--r--tools/perf/util/cpumap.c123
-rw-r--r--tools/perf/util/cpumap.h10
5 files changed, 138 insertions, 67 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 052de1780f76..220e6e7f0b97 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -39,7 +39,7 @@ static u64 user_interval = ULLONG_MAX;
39static u64 default_interval = 0; 39static u64 default_interval = 0;
40static u64 sample_type; 40static u64 sample_type;
41 41
42static int nr_cpus = 0; 42static struct cpu_map *cpus;
43static unsigned int page_size; 43static unsigned int page_size;
44static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = 128;
45static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
@@ -670,8 +670,8 @@ static int __cmd_record(int argc, const char **argv)
670 if (!system_wide && no_inherit && !cpu_list) { 670 if (!system_wide && no_inherit && !cpu_list) {
671 open_counters(-1); 671 open_counters(-1);
672 } else { 672 } else {
673 for (i = 0; i < nr_cpus; i++) 673 for (i = 0; i < cpus->nr; i++)
674 open_counters(cpumap[i]); 674 open_counters(cpus->map[i]);
675 } 675 }
676 676
677 perf_session__set_sample_type(session, sample_type); 677 perf_session__set_sample_type(session, sample_type);
@@ -927,14 +927,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
927 thread_num = 1; 927 thread_num = 1;
928 } 928 }
929 929
930 nr_cpus = read_cpu_map(cpu_list); 930 cpus = cpu_map__new(cpu_list);
931 if (nr_cpus < 1) { 931 if (cpus == NULL) {
932 perror("failed to collect number of CPUs"); 932 perror("failed to parse CPUs map");
933 return -1; 933 return -1;
934 } 934 }
935 935
936 list_for_each_entry(pos, &evsel_list, node) { 936 list_for_each_entry(pos, &evsel_list, node) {
937 if (perf_evsel__alloc_fd(pos, nr_cpus, thread_num) < 0) 937 if (perf_evsel__alloc_fd(pos, cpus->nr, thread_num) < 0)
938 goto out_free_fd; 938 goto out_free_fd;
939 } 939 }
940 event_array = malloc( 940 event_array = malloc(
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 065e79eb2142..3f4a431fb5a4 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -72,7 +72,7 @@ static struct perf_event_attr default_attrs[] = {
72}; 72};
73 73
74static bool system_wide = false; 74static bool system_wide = false;
75static int nr_cpus = 0; 75static struct cpu_map *cpus;
76static int run_idx = 0; 76static int run_idx = 0;
77 77
78static int run_count = 1; 78static int run_count = 1;
@@ -167,7 +167,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
167 PERF_FORMAT_TOTAL_TIME_RUNNING; 167 PERF_FORMAT_TOTAL_TIME_RUNNING;
168 168
169 if (system_wide) 169 if (system_wide)
170 return perf_evsel__open_per_cpu(evsel, nr_cpus, cpumap); 170 return perf_evsel__open_per_cpu(evsel, cpus->nr, cpus->map);
171 171
172 attr->inherit = !no_inherit; 172 attr->inherit = !no_inherit;
173 if (target_pid == -1 && target_tid == -1) { 173 if (target_pid == -1 && target_tid == -1) {
@@ -200,7 +200,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
200 u64 *count = counter->counts->aggr.values; 200 u64 *count = counter->counts->aggr.values;
201 int i; 201 int i;
202 202
203 if (__perf_evsel__read(counter, nr_cpus, thread_num, scale) < 0) 203 if (__perf_evsel__read(counter, cpus->nr, thread_num, scale) < 0)
204 return -1; 204 return -1;
205 205
206 for (i = 0; i < 3; i++) 206 for (i = 0; i < 3; i++)
@@ -233,7 +233,7 @@ static int read_counter(struct perf_evsel *counter)
233 u64 *count; 233 u64 *count;
234 int cpu; 234 int cpu;
235 235
236 for (cpu = 0; cpu < nr_cpus; cpu++) { 236 for (cpu = 0; cpu < cpus->nr; cpu++) {
237 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 237 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
238 return -1; 238 return -1;
239 239
@@ -259,9 +259,6 @@ static int run_perf_stat(int argc __used, const char **argv)
259 const bool forks = (argc > 0); 259 const bool forks = (argc > 0);
260 char buf; 260 char buf;
261 261
262 if (!system_wide)
263 nr_cpus = 1;
264
265 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 262 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
266 perror("failed to create pipes"); 263 perror("failed to create pipes");
267 exit(1); 264 exit(1);
@@ -351,12 +348,12 @@ static int run_perf_stat(int argc __used, const char **argv)
351 if (no_aggr) { 348 if (no_aggr) {
352 list_for_each_entry(counter, &evsel_list, node) { 349 list_for_each_entry(counter, &evsel_list, node) {
353 read_counter(counter); 350 read_counter(counter);
354 perf_evsel__close_fd(counter, nr_cpus, 1); 351 perf_evsel__close_fd(counter, cpus->nr, 1);
355 } 352 }
356 } else { 353 } else {
357 list_for_each_entry(counter, &evsel_list, node) { 354 list_for_each_entry(counter, &evsel_list, node) {
358 read_counter_aggr(counter); 355 read_counter_aggr(counter);
359 perf_evsel__close_fd(counter, nr_cpus, thread_num); 356 perf_evsel__close_fd(counter, cpus->nr, thread_num);
360 } 357 }
361 } 358 }
362 359
@@ -384,7 +381,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
384 if (no_aggr) 381 if (no_aggr)
385 sprintf(cpustr, "CPU%*d%s", 382 sprintf(cpustr, "CPU%*d%s",
386 csv_output ? 0 : -4, 383 csv_output ? 0 : -4,
387 cpumap[cpu], csv_sep); 384 cpus->map[cpu], csv_sep);
388 385
389 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 386 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
390 387
@@ -412,7 +409,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
412 if (no_aggr) 409 if (no_aggr)
413 sprintf(cpustr, "CPU%*d%s", 410 sprintf(cpustr, "CPU%*d%s",
414 csv_output ? 0 : -4, 411 csv_output ? 0 : -4,
415 cpumap[cpu], csv_sep); 412 cpus->map[cpu], csv_sep);
416 else 413 else
417 cpu = 0; 414 cpu = 0;
418 415
@@ -498,14 +495,14 @@ static void print_counter(struct perf_evsel *counter)
498 u64 ena, run, val; 495 u64 ena, run, val;
499 int cpu; 496 int cpu;
500 497
501 for (cpu = 0; cpu < nr_cpus; cpu++) { 498 for (cpu = 0; cpu < cpus->nr; cpu++) {
502 val = counter->counts->cpu[cpu].val; 499 val = counter->counts->cpu[cpu].val;
503 ena = counter->counts->cpu[cpu].ena; 500 ena = counter->counts->cpu[cpu].ena;
504 run = counter->counts->cpu[cpu].run; 501 run = counter->counts->cpu[cpu].run;
505 if (run == 0 || ena == 0) { 502 if (run == 0 || ena == 0) {
506 fprintf(stderr, "CPU%*d%s%*s%s%-24s", 503 fprintf(stderr, "CPU%*d%s%*s%s%-24s",
507 csv_output ? 0 : -4, 504 csv_output ? 0 : -4,
508 cpumap[cpu], csv_sep, 505 cpus->map[cpu], csv_sep,
509 csv_output ? 0 : 18, 506 csv_output ? 0 : 18,
510 "<not counted>", csv_sep, 507 "<not counted>", csv_sep,
511 event_name(counter)); 508 event_name(counter));
@@ -697,12 +694,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
697 } 694 }
698 695
699 if (system_wide) 696 if (system_wide)
700 nr_cpus = read_cpu_map(cpu_list); 697 cpus = cpu_map__new(cpu_list);
701 else 698 else
702 nr_cpus = 1; 699 cpus = cpu_map__dummy_new();
703 700
704 if (nr_cpus < 1) 701 if (cpus == NULL) {
702 perror("failed to parse CPUs map");
705 usage_with_options(stat_usage, options); 703 usage_with_options(stat_usage, options);
704 return -1;
705 }
706 706
707 if (target_pid != -1) { 707 if (target_pid != -1) {
708 target_tid = target_pid; 708 target_tid = target_pid;
@@ -723,8 +723,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
723 723
724 list_for_each_entry(pos, &evsel_list, node) { 724 list_for_each_entry(pos, &evsel_list, node) {
725 if (perf_evsel__alloc_stat_priv(pos) < 0 || 725 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
726 perf_evsel__alloc_counts(pos, nr_cpus) < 0 || 726 perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
727 perf_evsel__alloc_fd(pos, nr_cpus, thread_num) < 0) 727 perf_evsel__alloc_fd(pos, cpus->nr, thread_num) < 0)
728 goto out_free_fd; 728 goto out_free_fd;
729 } 729 }
730 730
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 27b9c14a0a07..0e426665716d 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -71,7 +71,7 @@ static int target_tid = -1;
71static pid_t *all_tids = NULL; 71static pid_t *all_tids = NULL;
72static int thread_num = 0; 72static int thread_num = 0;
73static bool inherit = false; 73static bool inherit = false;
74static int nr_cpus = 0; 74static struct cpu_map *cpus;
75static int realtime_prio = 0; 75static int realtime_prio = 0;
76static bool group = false; 76static bool group = false;
77static unsigned int page_size; 77static unsigned int page_size;
@@ -564,12 +564,12 @@ static void print_sym_table(void)
564 printf(" (all"); 564 printf(" (all");
565 565
566 if (cpu_list) 566 if (cpu_list)
567 printf(", CPU%s: %s)\n", nr_cpus > 1 ? "s" : "", cpu_list); 567 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
568 else { 568 else {
569 if (target_tid != -1) 569 if (target_tid != -1)
570 printf(")\n"); 570 printf(")\n");
571 else 571 else
572 printf(", %d CPU%s)\n", nr_cpus, nr_cpus > 1 ? "s" : ""); 572 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
573 } 573 }
574 574
575 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 575 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -1197,7 +1197,7 @@ static void perf_session__mmap_read(struct perf_session *self)
1197 struct perf_evsel *counter; 1197 struct perf_evsel *counter;
1198 int i, thread_index; 1198 int i, thread_index;
1199 1199
1200 for (i = 0; i < nr_cpus; i++) { 1200 for (i = 0; i < cpus->nr; i++) {
1201 list_for_each_entry(counter, &evsel_list, node) { 1201 list_for_each_entry(counter, &evsel_list, node) {
1202 for (thread_index = 0; 1202 for (thread_index = 0;
1203 thread_index < thread_num; 1203 thread_index < thread_num;
@@ -1221,7 +1221,7 @@ static void start_counter(int i, struct perf_evsel *evsel)
1221 int thread_index; 1221 int thread_index;
1222 1222
1223 if (target_tid == -1) 1223 if (target_tid == -1)
1224 cpu = cpumap[i]; 1224 cpu = cpus->map[i];
1225 1225
1226 attr = &evsel->attr; 1226 attr = &evsel->attr;
1227 1227
@@ -1310,7 +1310,7 @@ static int __cmd_top(void)
1310 else 1310 else
1311 event__synthesize_threads(event__process, session); 1311 event__synthesize_threads(event__process, session);
1312 1312
1313 for (i = 0; i < nr_cpus; i++) { 1313 for (i = 0; i < cpus->nr; i++) {
1314 group_fd = -1; 1314 group_fd = -1;
1315 list_for_each_entry(counter, &evsel_list, node) 1315 list_for_each_entry(counter, &evsel_list, node)
1316 start_counter(i, counter); 1316 start_counter(i, counter);
@@ -1460,16 +1460,16 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1460 } 1460 }
1461 1461
1462 if (target_tid != -1) 1462 if (target_tid != -1)
1463 nr_cpus = 1; 1463 cpus = cpu_map__dummy_new();
1464 else 1464 else
1465 nr_cpus = read_cpu_map(cpu_list); 1465 cpus = cpu_map__new(cpu_list);
1466 1466
1467 if (nr_cpus < 1) 1467 if (cpus == NULL)
1468 usage_with_options(top_usage, options); 1468 usage_with_options(top_usage, options);
1469 1469
1470 list_for_each_entry(pos, &evsel_list, node) { 1470 list_for_each_entry(pos, &evsel_list, node) {
1471 if (perf_evsel__alloc_mmap_per_thread(pos, nr_cpus, thread_num) < 0 || 1471 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, thread_num) < 0 ||
1472 perf_evsel__alloc_fd(pos, nr_cpus, thread_num) < 0) 1472 perf_evsel__alloc_fd(pos, cpus->nr, thread_num) < 0)
1473 goto out_free_fd; 1473 goto out_free_fd;
1474 /* 1474 /*
1475 * Fill in the ones not specifically initialized via -c: 1475 * Fill in the ones not specifically initialized via -c:
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 0f9b8d7a7d7e..3ccaa1043383 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -4,32 +4,53 @@
4#include <assert.h> 4#include <assert.h>
5#include <stdio.h> 5#include <stdio.h>
6 6
7int cpumap[MAX_NR_CPUS]; 7static struct cpu_map *cpu_map__default_new(void)
8
9static int default_cpu_map(void)
10{ 8{
11 int nr_cpus, i; 9 struct cpu_map *cpus;
10 int nr_cpus;
12 11
13 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 12 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
14 assert(nr_cpus <= MAX_NR_CPUS); 13 if (nr_cpus < 0)
15 assert((int)nr_cpus >= 0); 14 return NULL;
15
16 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
17 if (cpus != NULL) {
18 int i;
19 for (i = 0; i < nr_cpus; ++i)
20 cpus->map[i] = i;
16 21
17 for (i = 0; i < nr_cpus; ++i) 22 cpus->nr = nr_cpus;
18 cpumap[i] = i; 23 }
19 24
20 return nr_cpus; 25 return cpus;
21} 26}
22 27
23static int read_all_cpu_map(void) 28static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
24{ 29{
30 size_t payload_size = nr_cpus * sizeof(int);
31 struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
32
33 if (cpus != NULL) {
34 cpus->nr = nr_cpus;
35 memcpy(cpus->map, tmp_cpus, payload_size);
36 }
37
38 return cpus;
39}
40
41static struct cpu_map *cpu_map__read_all_cpu_map(void)
42{
43 struct cpu_map *cpus = NULL;
25 FILE *onlnf; 44 FILE *onlnf;
26 int nr_cpus = 0; 45 int nr_cpus = 0;
46 int *tmp_cpus = NULL, *tmp;
47 int max_entries = 0;
27 int n, cpu, prev; 48 int n, cpu, prev;
28 char sep; 49 char sep;
29 50
30 onlnf = fopen("/sys/devices/system/cpu/online", "r"); 51 onlnf = fopen("/sys/devices/system/cpu/online", "r");
31 if (!onlnf) 52 if (!onlnf)
32 return default_cpu_map(); 53 return cpu_map__default_new();
33 54
34 sep = 0; 55 sep = 0;
35 prev = -1; 56 prev = -1;
@@ -38,12 +59,28 @@ static int read_all_cpu_map(void)
38 if (n <= 0) 59 if (n <= 0)
39 break; 60 break;
40 if (prev >= 0) { 61 if (prev >= 0) {
41 assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); 62 int new_max = nr_cpus + cpu - prev - 1;
63
64 if (new_max >= max_entries) {
65 max_entries = new_max + MAX_NR_CPUS / 2;
66 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
67 if (tmp == NULL)
68 goto out_free_tmp;
69 tmp_cpus = tmp;
70 }
71
42 while (++prev < cpu) 72 while (++prev < cpu)
43 cpumap[nr_cpus++] = prev; 73 tmp_cpus[nr_cpus++] = prev;
74 }
75 if (nr_cpus == max_entries) {
76 max_entries += MAX_NR_CPUS;
77 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
78 if (tmp == NULL)
79 goto out_free_tmp;
80 tmp_cpus = tmp;
44 } 81 }
45 assert (nr_cpus < MAX_NR_CPUS); 82
46 cpumap[nr_cpus++] = cpu; 83 tmp_cpus[nr_cpus++] = cpu;
47 if (n == 2 && sep == '-') 84 if (n == 2 && sep == '-')
48 prev = cpu; 85 prev = cpu;
49 else 86 else
@@ -51,24 +88,31 @@ static int read_all_cpu_map(void)
51 if (n == 1 || sep == '\n') 88 if (n == 1 || sep == '\n')
52 break; 89 break;
53 } 90 }
54 fclose(onlnf);
55 if (nr_cpus > 0)
56 return nr_cpus;
57 91
58 return default_cpu_map(); 92 if (nr_cpus > 0)
93 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
94 else
95 cpus = cpu_map__default_new();
96out_free_tmp:
97 free(tmp_cpus);
98 fclose(onlnf);
99 return cpus;
59} 100}
60 101
61int read_cpu_map(const char *cpu_list) 102struct cpu_map *cpu_map__new(const char *cpu_list)
62{ 103{
104 struct cpu_map *cpus = NULL;
63 unsigned long start_cpu, end_cpu = 0; 105 unsigned long start_cpu, end_cpu = 0;
64 char *p = NULL; 106 char *p = NULL;
65 int i, nr_cpus = 0; 107 int i, nr_cpus = 0;
108 int *tmp_cpus = NULL, *tmp;
109 int max_entries = 0;
66 110
67 if (!cpu_list) 111 if (!cpu_list)
68 return read_all_cpu_map(); 112 return cpu_map__read_all_cpu_map();
69 113
70 if (!isdigit(*cpu_list)) 114 if (!isdigit(*cpu_list))
71 goto invalid; 115 goto out;
72 116
73 while (isdigit(*cpu_list)) { 117 while (isdigit(*cpu_list)) {
74 p = NULL; 118 p = NULL;
@@ -94,21 +138,42 @@ int read_cpu_map(const char *cpu_list)
94 for (; start_cpu <= end_cpu; start_cpu++) { 138 for (; start_cpu <= end_cpu; start_cpu++) {
95 /* check for duplicates */ 139 /* check for duplicates */
96 for (i = 0; i < nr_cpus; i++) 140 for (i = 0; i < nr_cpus; i++)
97 if (cpumap[i] == (int)start_cpu) 141 if (tmp_cpus[i] == (int)start_cpu)
98 goto invalid; 142 goto invalid;
99 143
100 assert(nr_cpus < MAX_NR_CPUS); 144 if (nr_cpus == max_entries) {
101 cpumap[nr_cpus++] = (int)start_cpu; 145 max_entries += MAX_NR_CPUS;
146 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
147 if (tmp == NULL)
148 goto invalid;
149 tmp_cpus = tmp;
150 }
151 tmp_cpus[nr_cpus++] = (int)start_cpu;
102 } 152 }
103 if (*p) 153 if (*p)
104 ++p; 154 ++p;
105 155
106 cpu_list = p; 156 cpu_list = p;
107 } 157 }
108 if (nr_cpus > 0)
109 return nr_cpus;
110 158
111 return default_cpu_map(); 159 if (nr_cpus > 0)
160 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
161 else
162 cpus = cpu_map__default_new();
112invalid: 163invalid:
113 return -1; 164 free(tmp_cpus);
165out:
166 return cpus;
167}
168
169struct cpu_map *cpu_map__dummy_new(void)
170{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
172
173 if (cpus != NULL) {
174 cpus->nr = 1;
175 cpus->map[0] = -1;
176 }
177
178 return cpus;
114} 179}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 3e60f56e490e..f7a4f42f6307 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,7 +1,13 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4extern int read_cpu_map(const char *cpu_list); 4struct cpu_map {
5extern int cpumap[]; 5 int nr;
6 int map[];
7};
8
9struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void);
11void *cpu_map__delete(struct cpu_map *map);
6 12
7#endif /* __PERF_CPUMAP_H */ 13#endif /* __PERF_CPUMAP_H */