summaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r--tools/perf/builtin-stat.c328
1 files changed, 265 insertions, 63 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c247faca7127..99848761f573 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -65,6 +65,11 @@
65#define CNTR_NOT_SUPPORTED "<not supported>" 65#define CNTR_NOT_SUPPORTED "<not supported>"
66#define CNTR_NOT_COUNTED "<not counted>" 66#define CNTR_NOT_COUNTED "<not counted>"
67 67
68static void print_stat(int argc, const char **argv);
69static void print_counter_aggr(struct perf_evsel *counter, char *prefix);
70static void print_counter(struct perf_evsel *counter, char *prefix);
71static void print_aggr_socket(char *prefix);
72
68static struct perf_evlist *evsel_list; 73static struct perf_evlist *evsel_list;
69 74
70static struct perf_target target = { 75static struct perf_target target = {
@@ -75,6 +80,7 @@ static int run_count = 1;
75static bool no_inherit = false; 80static bool no_inherit = false;
76static bool scale = true; 81static bool scale = true;
77static bool no_aggr = false; 82static bool no_aggr = false;
83static bool aggr_socket = false;
78static pid_t child_pid = -1; 84static pid_t child_pid = -1;
79static bool null_run = false; 85static bool null_run = false;
80static int detailed_run = 0; 86static int detailed_run = 0;
@@ -87,6 +93,9 @@ static FILE *output = NULL;
87static const char *pre_cmd = NULL; 93static const char *pre_cmd = NULL;
88static const char *post_cmd = NULL; 94static const char *post_cmd = NULL;
89static bool sync_run = false; 95static bool sync_run = false;
96static unsigned int interval = 0;
97static struct timespec ref_time;
98static struct cpu_map *sock_map;
90 99
91static volatile int done = 0; 100static volatile int done = 0;
92 101
@@ -94,6 +103,28 @@ struct perf_stat {
94 struct stats res_stats[3]; 103 struct stats res_stats[3];
95}; 104};
96 105
106static inline void diff_timespec(struct timespec *r, struct timespec *a,
107 struct timespec *b)
108{
109 r->tv_sec = a->tv_sec - b->tv_sec;
110 if (a->tv_nsec < b->tv_nsec) {
111 r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec;
112 r->tv_sec--;
113 } else {
114 r->tv_nsec = a->tv_nsec - b->tv_nsec ;
115 }
116}
117
118static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
119{
120 return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
121}
122
123static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
124{
125 return perf_evsel__cpus(evsel)->nr;
126}
127
97static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 128static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
98{ 129{
99 evsel->priv = zalloc(sizeof(struct perf_stat)); 130 evsel->priv = zalloc(sizeof(struct perf_stat));
@@ -106,14 +137,27 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
106 evsel->priv = NULL; 137 evsel->priv = NULL;
107} 138}
108 139
109static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) 140static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
110{ 141{
111 return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; 142 void *addr;
143 size_t sz;
144
145 sz = sizeof(*evsel->counts) +
146 (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values));
147
148 addr = zalloc(sz);
149 if (!addr)
150 return -ENOMEM;
151
152 evsel->prev_raw_counts = addr;
153
154 return 0;
112} 155}
113 156
114static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) 157static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
115{ 158{
116 return perf_evsel__cpus(evsel)->nr; 159 free(evsel->prev_raw_counts);
160 evsel->prev_raw_counts = NULL;
117} 161}
118 162
119static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 163static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
@@ -132,8 +176,6 @@ static struct stats walltime_nsecs_stats;
132static int create_perf_stat_counter(struct perf_evsel *evsel) 176static int create_perf_stat_counter(struct perf_evsel *evsel)
133{ 177{
134 struct perf_event_attr *attr = &evsel->attr; 178 struct perf_event_attr *attr = &evsel->attr;
135 bool exclude_guest_missing = false;
136 int ret;
137 179
138 if (scale) 180 if (scale)
139 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 181 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -141,38 +183,16 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
141 183
142 attr->inherit = !no_inherit; 184 attr->inherit = !no_inherit;
143 185
144retry: 186 if (perf_target__has_cpu(&target))
145 if (exclude_guest_missing) 187 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
146 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
147
148 if (perf_target__has_cpu(&target)) {
149 ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
150 if (ret)
151 goto check_ret;
152 return 0;
153 }
154 188
155 if (!perf_target__has_task(&target) && 189 if (!perf_target__has_task(&target) &&
156 !perf_evsel__is_group_member(evsel)) { 190 perf_evsel__is_group_leader(evsel)) {
157 attr->disabled = 1; 191 attr->disabled = 1;
158 attr->enable_on_exec = 1; 192 attr->enable_on_exec = 1;
159 } 193 }
160 194
161 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads); 195 return perf_evsel__open_per_thread(evsel, evsel_list->threads);
162 if (!ret)
163 return 0;
164 /* fall through */
165check_ret:
166 if (ret && errno == EINVAL) {
167 if (!exclude_guest_missing &&
168 (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
169 pr_debug("Old kernel, cannot exclude "
170 "guest or host samples.\n");
171 exclude_guest_missing = true;
172 goto retry;
173 }
174 }
175 return ret;
176} 196}
177 197
178/* 198/*
@@ -269,15 +289,79 @@ static int read_counter(struct perf_evsel *counter)
269 return 0; 289 return 0;
270} 290}
271 291
292static void print_interval(void)
293{
294 static int num_print_interval;
295 struct perf_evsel *counter;
296 struct perf_stat *ps;
297 struct timespec ts, rs;
298 char prefix[64];
299
300 if (no_aggr) {
301 list_for_each_entry(counter, &evsel_list->entries, node) {
302 ps = counter->priv;
303 memset(ps->res_stats, 0, sizeof(ps->res_stats));
304 read_counter(counter);
305 }
306 } else {
307 list_for_each_entry(counter, &evsel_list->entries, node) {
308 ps = counter->priv;
309 memset(ps->res_stats, 0, sizeof(ps->res_stats));
310 read_counter_aggr(counter);
311 }
312 }
313 clock_gettime(CLOCK_MONOTONIC, &ts);
314 diff_timespec(&rs, &ts, &ref_time);
315 sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep);
316
317 if (num_print_interval == 0 && !csv_output) {
318 if (aggr_socket)
319 fprintf(output, "# time socket cpus counts events\n");
320 else if (no_aggr)
321 fprintf(output, "# time CPU counts events\n");
322 else
323 fprintf(output, "# time counts events\n");
324 }
325
326 if (++num_print_interval == 25)
327 num_print_interval = 0;
328
329 if (aggr_socket)
330 print_aggr_socket(prefix);
331 else if (no_aggr) {
332 list_for_each_entry(counter, &evsel_list->entries, node)
333 print_counter(counter, prefix);
334 } else {
335 list_for_each_entry(counter, &evsel_list->entries, node)
336 print_counter_aggr(counter, prefix);
337 }
338}
339
272static int __run_perf_stat(int argc __maybe_unused, const char **argv) 340static int __run_perf_stat(int argc __maybe_unused, const char **argv)
273{ 341{
342 char msg[512];
274 unsigned long long t0, t1; 343 unsigned long long t0, t1;
275 struct perf_evsel *counter; 344 struct perf_evsel *counter;
345 struct timespec ts;
276 int status = 0; 346 int status = 0;
277 int child_ready_pipe[2], go_pipe[2]; 347 int child_ready_pipe[2], go_pipe[2];
278 const bool forks = (argc > 0); 348 const bool forks = (argc > 0);
279 char buf; 349 char buf;
280 350
351 if (interval) {
352 ts.tv_sec = interval / 1000;
353 ts.tv_nsec = (interval % 1000) * 1000000;
354 } else {
355 ts.tv_sec = 1;
356 ts.tv_nsec = 0;
357 }
358
359 if (aggr_socket
360 && cpu_map__build_socket_map(evsel_list->cpus, &sock_map)) {
361 perror("cannot build socket map");
362 return -1;
363 }
364
281 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 365 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
282 perror("failed to create pipes"); 366 perror("failed to create pipes");
283 return -1; 367 return -1;
@@ -348,20 +432,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
348 continue; 432 continue;
349 } 433 }
350 434
351 if (errno == EPERM || errno == EACCES) { 435 perf_evsel__open_strerror(counter, &target,
352 error("You may not have permission to collect %sstats.\n" 436 errno, msg, sizeof(msg));
353 "\t Consider tweaking" 437 ui__error("%s\n", msg);
354 " /proc/sys/kernel/perf_event_paranoid or running as root.", 438
355 target.system_wide ? "system-wide " : "");
356 } else {
357 error("open_counter returned with %d (%s). "
358 "/bin/dmesg may provide additional information.\n",
359 errno, strerror(errno));
360 }
361 if (child_pid != -1) 439 if (child_pid != -1)
362 kill(child_pid, SIGTERM); 440 kill(child_pid, SIGTERM);
363 441
364 pr_err("Not all events could be opened.\n");
365 return -1; 442 return -1;
366 } 443 }
367 counter->supported = true; 444 counter->supported = true;
@@ -377,14 +454,25 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
377 * Enable counters and exec the command: 454 * Enable counters and exec the command:
378 */ 455 */
379 t0 = rdclock(); 456 t0 = rdclock();
457 clock_gettime(CLOCK_MONOTONIC, &ref_time);
380 458
381 if (forks) { 459 if (forks) {
382 close(go_pipe[1]); 460 close(go_pipe[1]);
461 if (interval) {
462 while (!waitpid(child_pid, &status, WNOHANG)) {
463 nanosleep(&ts, NULL);
464 print_interval();
465 }
466 }
383 wait(&status); 467 wait(&status);
384 if (WIFSIGNALED(status)) 468 if (WIFSIGNALED(status))
385 psignal(WTERMSIG(status), argv[0]); 469 psignal(WTERMSIG(status), argv[0]);
386 } else { 470 } else {
387 while(!done) sleep(1); 471 while (!done) {
472 nanosleep(&ts, NULL);
473 if (interval)
474 print_interval();
475 }
388 } 476 }
389 477
390 t1 = rdclock(); 478 t1 = rdclock();
@@ -454,13 +542,21 @@ static void print_noise(struct perf_evsel *evsel, double avg)
454 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 542 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
455} 543}
456 544
457static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 545static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
458{ 546{
459 double msecs = avg / 1e6; 547 double msecs = avg / 1e6;
460 char cpustr[16] = { '\0', }; 548 char cpustr[16] = { '\0', };
461 const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s"; 549 const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s";
462 550
463 if (no_aggr) 551 if (aggr_socket)
552 sprintf(cpustr, "S%*d%s%*d%s",
553 csv_output ? 0 : -5,
554 cpu,
555 csv_sep,
556 csv_output ? 0 : 4,
557 nr,
558 csv_sep);
559 else if (no_aggr)
464 sprintf(cpustr, "CPU%*d%s", 560 sprintf(cpustr, "CPU%*d%s",
465 csv_output ? 0 : -4, 561 csv_output ? 0 : -4,
466 perf_evsel__cpus(evsel)->map[cpu], csv_sep); 562 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
@@ -470,7 +566,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
470 if (evsel->cgrp) 566 if (evsel->cgrp)
471 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 567 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
472 568
473 if (csv_output) 569 if (csv_output || interval)
474 return; 570 return;
475 571
476 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 572 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
@@ -659,7 +755,7 @@ static void print_ll_cache_misses(int cpu,
659 fprintf(output, " of all LL-cache hits "); 755 fprintf(output, " of all LL-cache hits ");
660} 756}
661 757
662static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 758static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
663{ 759{
664 double total, ratio = 0.0; 760 double total, ratio = 0.0;
665 char cpustr[16] = { '\0', }; 761 char cpustr[16] = { '\0', };
@@ -672,7 +768,15 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
672 else 768 else
673 fmt = "%s%18.0f%s%-25s"; 769 fmt = "%s%18.0f%s%-25s";
674 770
675 if (no_aggr) 771 if (aggr_socket)
772 sprintf(cpustr, "S%*d%s%*d%s",
773 csv_output ? 0 : -5,
774 cpu,
775 csv_sep,
776 csv_output ? 0 : 4,
777 nr,
778 csv_sep);
779 else if (no_aggr)
676 sprintf(cpustr, "CPU%*d%s", 780 sprintf(cpustr, "CPU%*d%s",
677 csv_output ? 0 : -4, 781 csv_output ? 0 : -4,
678 perf_evsel__cpus(evsel)->map[cpu], csv_sep); 782 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
@@ -684,12 +788,11 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
684 if (evsel->cgrp) 788 if (evsel->cgrp)
685 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 789 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
686 790
687 if (csv_output) 791 if (csv_output || interval)
688 return; 792 return;
689 793
690 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 794 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
691 total = avg_stats(&runtime_cycles_stats[cpu]); 795 total = avg_stats(&runtime_cycles_stats[cpu]);
692
693 if (total) 796 if (total)
694 ratio = avg / total; 797 ratio = avg / total;
695 798
@@ -779,16 +882,83 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
779 } 882 }
780} 883}
781 884
885static void print_aggr_socket(char *prefix)
886{
887 struct perf_evsel *counter;
888 u64 ena, run, val;
889 int cpu, s, s2, sock, nr;
890
891 if (!sock_map)
892 return;
893
894 for (s = 0; s < sock_map->nr; s++) {
895 sock = cpu_map__socket(sock_map, s);
896 list_for_each_entry(counter, &evsel_list->entries, node) {
897 val = ena = run = 0;
898 nr = 0;
899 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
900 s2 = cpu_map__get_socket(evsel_list->cpus, cpu);
901 if (s2 != sock)
902 continue;
903 val += counter->counts->cpu[cpu].val;
904 ena += counter->counts->cpu[cpu].ena;
905 run += counter->counts->cpu[cpu].run;
906 nr++;
907 }
908 if (prefix)
909 fprintf(output, "%s", prefix);
910
911 if (run == 0 || ena == 0) {
912 fprintf(output, "S%*d%s%*d%s%*s%s%*s",
913 csv_output ? 0 : -5,
914 s,
915 csv_sep,
916 csv_output ? 0 : 4,
917 nr,
918 csv_sep,
919 csv_output ? 0 : 18,
920 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
921 csv_sep,
922 csv_output ? 0 : -24,
923 perf_evsel__name(counter));
924 if (counter->cgrp)
925 fprintf(output, "%s%s",
926 csv_sep, counter->cgrp->name);
927
928 fputc('\n', output);
929 continue;
930 }
931
932 if (nsec_counter(counter))
933 nsec_printout(sock, nr, counter, val);
934 else
935 abs_printout(sock, nr, counter, val);
936
937 if (!csv_output) {
938 print_noise(counter, 1.0);
939
940 if (run != ena)
941 fprintf(output, " (%.2f%%)",
942 100.0 * run / ena);
943 }
944 fputc('\n', output);
945 }
946 }
947}
948
782/* 949/*
783 * Print out the results of a single counter: 950 * Print out the results of a single counter:
784 * aggregated counts in system-wide mode 951 * aggregated counts in system-wide mode
785 */ 952 */
786static void print_counter_aggr(struct perf_evsel *counter) 953static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
787{ 954{
788 struct perf_stat *ps = counter->priv; 955 struct perf_stat *ps = counter->priv;
789 double avg = avg_stats(&ps->res_stats[0]); 956 double avg = avg_stats(&ps->res_stats[0]);
790 int scaled = counter->counts->scaled; 957 int scaled = counter->counts->scaled;
791 958
959 if (prefix)
960 fprintf(output, "%s", prefix);
961
792 if (scaled == -1) { 962 if (scaled == -1) {
793 fprintf(output, "%*s%s%*s", 963 fprintf(output, "%*s%s%*s",
794 csv_output ? 0 : 18, 964 csv_output ? 0 : 18,
@@ -805,9 +975,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
805 } 975 }
806 976
807 if (nsec_counter(counter)) 977 if (nsec_counter(counter))
808 nsec_printout(-1, counter, avg); 978 nsec_printout(-1, 0, counter, avg);
809 else 979 else
810 abs_printout(-1, counter, avg); 980 abs_printout(-1, 0, counter, avg);
811 981
812 print_noise(counter, avg); 982 print_noise(counter, avg);
813 983
@@ -831,7 +1001,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
831 * Print out the results of a single counter: 1001 * Print out the results of a single counter:
832 * does not use aggregated count in system-wide 1002 * does not use aggregated count in system-wide
833 */ 1003 */
834static void print_counter(struct perf_evsel *counter) 1004static void print_counter(struct perf_evsel *counter, char *prefix)
835{ 1005{
836 u64 ena, run, val; 1006 u64 ena, run, val;
837 int cpu; 1007 int cpu;
@@ -840,6 +1010,10 @@ static void print_counter(struct perf_evsel *counter)
840 val = counter->counts->cpu[cpu].val; 1010 val = counter->counts->cpu[cpu].val;
841 ena = counter->counts->cpu[cpu].ena; 1011 ena = counter->counts->cpu[cpu].ena;
842 run = counter->counts->cpu[cpu].run; 1012 run = counter->counts->cpu[cpu].run;
1013
1014 if (prefix)
1015 fprintf(output, "%s", prefix);
1016
843 if (run == 0 || ena == 0) { 1017 if (run == 0 || ena == 0) {
844 fprintf(output, "CPU%*d%s%*s%s%*s", 1018 fprintf(output, "CPU%*d%s%*s%s%*s",
845 csv_output ? 0 : -4, 1019 csv_output ? 0 : -4,
@@ -859,9 +1033,9 @@ static void print_counter(struct perf_evsel *counter)
859 } 1033 }
860 1034
861 if (nsec_counter(counter)) 1035 if (nsec_counter(counter))
862 nsec_printout(cpu, counter, val); 1036 nsec_printout(cpu, 0, counter, val);
863 else 1037 else
864 abs_printout(cpu, counter, val); 1038 abs_printout(cpu, 0, counter, val);
865 1039
866 if (!csv_output) { 1040 if (!csv_output) {
867 print_noise(counter, 1.0); 1041 print_noise(counter, 1.0);
@@ -899,12 +1073,14 @@ static void print_stat(int argc, const char **argv)
899 fprintf(output, ":\n\n"); 1073 fprintf(output, ":\n\n");
900 } 1074 }
901 1075
902 if (no_aggr) { 1076 if (aggr_socket)
1077 print_aggr_socket(NULL);
1078 else if (no_aggr) {
903 list_for_each_entry(counter, &evsel_list->entries, node) 1079 list_for_each_entry(counter, &evsel_list->entries, node)
904 print_counter(counter); 1080 print_counter(counter, NULL);
905 } else { 1081 } else {
906 list_for_each_entry(counter, &evsel_list->entries, node) 1082 list_for_each_entry(counter, &evsel_list->entries, node)
907 print_counter_aggr(counter); 1083 print_counter_aggr(counter, NULL);
908 } 1084 }
909 1085
910 if (!csv_output) { 1086 if (!csv_output) {
@@ -925,7 +1101,7 @@ static volatile int signr = -1;
925 1101
926static void skip_signal(int signo) 1102static void skip_signal(int signo)
927{ 1103{
928 if(child_pid == -1) 1104 if ((child_pid == -1) || interval)
929 done = 1; 1105 done = 1;
930 1106
931 signr = signo; 1107 signr = signo;
@@ -1145,6 +1321,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1145 "command to run prior to the measured command"), 1321 "command to run prior to the measured command"),
1146 OPT_STRING(0, "post", &post_cmd, "command", 1322 OPT_STRING(0, "post", &post_cmd, "command",
1147 "command to run after to the measured command"), 1323 "command to run after to the measured command"),
1324 OPT_UINTEGER('I', "interval-print", &interval,
1325 "print counts at regular interval in ms (>= 100)"),
1326 OPT_BOOLEAN(0, "aggr-socket", &aggr_socket, "aggregate counts per processor socket"),
1148 OPT_END() 1327 OPT_END()
1149 }; 1328 };
1150 const char * const stat_usage[] = { 1329 const char * const stat_usage[] = {
@@ -1231,6 +1410,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1231 usage_with_options(stat_usage, options); 1410 usage_with_options(stat_usage, options);
1232 } 1411 }
1233 1412
1413 if (aggr_socket) {
1414 if (!perf_target__has_cpu(&target)) {
1415 fprintf(stderr, "--aggr-socket only available in system-wide mode (-a)\n");
1416 usage_with_options(stat_usage, options);
1417 }
1418 no_aggr = true;
1419 }
1420
1234 if (add_default_attributes()) 1421 if (add_default_attributes())
1235 goto out; 1422 goto out;
1236 1423
@@ -1245,12 +1432,23 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1245 usage_with_options(stat_usage, options); 1432 usage_with_options(stat_usage, options);
1246 return -1; 1433 return -1;
1247 } 1434 }
1435 if (interval && interval < 100) {
1436 pr_err("print interval must be >= 100ms\n");
1437 usage_with_options(stat_usage, options);
1438 return -1;
1439 }
1248 1440
1249 list_for_each_entry(pos, &evsel_list->entries, node) { 1441 list_for_each_entry(pos, &evsel_list->entries, node) {
1250 if (perf_evsel__alloc_stat_priv(pos) < 0 || 1442 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
1251 perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0) 1443 perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
1252 goto out_free_fd; 1444 goto out_free_fd;
1253 } 1445 }
1446 if (interval) {
1447 list_for_each_entry(pos, &evsel_list->entries, node) {
1448 if (perf_evsel__alloc_prev_raw_counts(pos) < 0)
1449 goto out_free_fd;
1450 }
1451 }
1254 1452
1255 /* 1453 /*
1256 * We dont want to block the signals - that would cause 1454 * We dont want to block the signals - that would cause
@@ -1260,6 +1458,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1260 */ 1458 */
1261 atexit(sig_atexit); 1459 atexit(sig_atexit);
1262 signal(SIGINT, skip_signal); 1460 signal(SIGINT, skip_signal);
1461 signal(SIGCHLD, skip_signal);
1263 signal(SIGALRM, skip_signal); 1462 signal(SIGALRM, skip_signal);
1264 signal(SIGABRT, skip_signal); 1463 signal(SIGABRT, skip_signal);
1265 1464
@@ -1272,11 +1471,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1272 status = run_perf_stat(argc, argv); 1471 status = run_perf_stat(argc, argv);
1273 } 1472 }
1274 1473
1275 if (status != -1) 1474 if (status != -1 && !interval)
1276 print_stat(argc, argv); 1475 print_stat(argc, argv);
1277out_free_fd: 1476out_free_fd:
1278 list_for_each_entry(pos, &evsel_list->entries, node) 1477 list_for_each_entry(pos, &evsel_list->entries, node) {
1279 perf_evsel__free_stat_priv(pos); 1478 perf_evsel__free_stat_priv(pos);
1479 perf_evsel__free_counts(pos);
1480 perf_evsel__free_prev_raw_counts(pos);
1481 }
1280 perf_evlist__delete_maps(evsel_list); 1482 perf_evlist__delete_maps(evsel_list);
1281out: 1483out:
1282 perf_evlist__delete(evsel_list); 1484 perf_evlist__delete(evsel_list);