aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/include/asm-generic/bitsperlong.h23
-rw-r--r--tools/include/linux/compiler.h11
-rw-r--r--tools/lib/api/fd/array.h1
-rw-r--r--tools/lib/api/fs/fs.c7
-rw-r--r--tools/lib/traceevent/event-parse.c3
-rw-r--r--tools/objtool/Makefile2
-rw-r--r--tools/objtool/builtin-check.c2
-rw-r--r--tools/perf/Documentation/perf-record.txt22
-rw-r--r--tools/perf/builtin-record.c113
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/tests/backward-ring-buffer.c14
-rw-r--r--tools/perf/util/evlist.c269
-rw-r--r--tools/perf/util/evlist.h47
-rw-r--r--tools/perf/util/evsel.c16
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/parse-events.c20
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/session.c22
-rw-r--r--tools/perf/util/sort.c8
-rw-r--r--tools/perf/util/util.h2
22 files changed, 441 insertions, 152 deletions
diff --git a/tools/include/asm-generic/bitsperlong.h b/tools/include/asm-generic/bitsperlong.h
index cfd661c6fc17..45eca517efb3 100644
--- a/tools/include/asm-generic/bitsperlong.h
+++ b/tools/include/asm-generic/bitsperlong.h
@@ -3,31 +3,12 @@
3 3
4#include <uapi/asm-generic/bitsperlong.h> 4#include <uapi/asm-generic/bitsperlong.h>
5 5
6/*
7 * In the kernel, where this file comes from, we can rely on CONFIG_64BIT,
8 * here we have to make amends with what the various compilers provides us
9 * to figure out if we're on a 64-bit machine...
10 */
11#ifdef __SIZEOF_LONG__ 6#ifdef __SIZEOF_LONG__
12# if __SIZEOF_LONG__ == 8 7#define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__)
13# define CONFIG_64BIT
14# endif
15#else 8#else
16# ifdef __WORDSIZE 9#define BITS_PER_LONG __WORDSIZE
17# if __WORDSIZE == 64
18# define CONFIG_64BIT
19# endif
20# else
21# error Failed to determine BITS_PER_LONG value
22# endif
23#endif 10#endif
24 11
25#ifdef CONFIG_64BIT
26#define BITS_PER_LONG 64
27#else
28#define BITS_PER_LONG 32
29#endif /* CONFIG_64BIT */
30
31#if BITS_PER_LONG != __BITS_PER_LONG 12#if BITS_PER_LONG != __BITS_PER_LONG
32#error Inconsistent word size. Check asm/bitsperlong.h 13#error Inconsistent word size. Check asm/bitsperlong.h
33#endif 14#endif
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index fa7208a32d76..e33fc1df3935 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -9,6 +9,17 @@
9# define __always_inline inline __attribute__((always_inline)) 9# define __always_inline inline __attribute__((always_inline))
10#endif 10#endif
11 11
12#ifdef __ANDROID__
13/*
14 * FIXME: Big hammer to get rid of tons of:
15 * "warning: always_inline function might not be inlinable"
16 *
17 * At least on android-ndk-r12/platforms/android-24/arch-arm
18 */
19#undef __always_inline
20#define __always_inline inline
21#endif
22
12#define __user 23#define __user
13 24
14#ifndef __attribute_const__ 25#ifndef __attribute_const__
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
index e87fd800fa8d..71287dddc05f 100644
--- a/tools/lib/api/fd/array.h
+++ b/tools/lib/api/fd/array.h
@@ -22,6 +22,7 @@ struct fdarray {
22 struct pollfd *entries; 22 struct pollfd *entries;
23 union { 23 union {
24 int idx; 24 int idx;
25 void *ptr;
25 } *priv; 26 } *priv;
26}; 27};
27 28
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 08556cf2c70d..ba7094b945ff 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -283,6 +283,11 @@ int filename__read_int(const char *filename, int *value)
283 return err; 283 return err;
284} 284}
285 285
286/*
287 * Parses @value out of @filename with strtoull.
288 * By using 0 for base, the strtoull detects the
289 * base automatically (see man strtoull).
290 */
286int filename__read_ull(const char *filename, unsigned long long *value) 291int filename__read_ull(const char *filename, unsigned long long *value)
287{ 292{
288 char line[64]; 293 char line[64];
@@ -292,7 +297,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)
292 return -1; 297 return -1;
293 298
294 if (read(fd, line, sizeof(line)) > 0) { 299 if (read(fd, line, sizeof(line)) > 0) {
295 *value = strtoull(line, NULL, 10); 300 *value = strtoull(line, NULL, 0);
296 if (*value != ULLONG_MAX) 301 if (*value != ULLONG_MAX)
297 err = 0; 302 err = 0;
298 } 303 }
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 3a7bd175f73c..664c90c8e22b 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -23,6 +23,7 @@
23 * Frederic Weisbecker gave his permission to relicense the code to 23 * Frederic Weisbecker gave his permission to relicense the code to
24 * the Lesser General Public License. 24 * the Lesser General Public License.
25 */ 25 */
26#include <inttypes.h>
26#include <stdio.h> 27#include <stdio.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h> 29#include <string.h>
@@ -33,7 +34,7 @@
33#include <limits.h> 34#include <limits.h>
34#include <linux/string.h> 35#include <linux/string.h>
35 36
36#include <netinet/ip6.h> 37#include <netinet/in.h>
37#include "event-parse.h" 38#include "event-parse.h"
38#include "event-utils.h" 39#include "event-utils.h"
39 40
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 9a3110cac604..1f75b0a046cc 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -26,7 +26,7 @@ OBJTOOL_IN := $(OBJTOOL)-in.o
26 26
27all: $(OBJTOOL) 27all: $(OBJTOOL)
28 28
29INCLUDES := -I$(srctree)/tools/include 29INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD) 31LDFLAGS += -lelf $(LIBSUBCMD)
32 32
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 92d84b277032..4ed30f45c6da 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -664,7 +664,7 @@ static int add_func_switch_tables(struct objtool_file *file,
664 struct symbol *func) 664 struct symbol *func)
665{ 665{
666 struct instruction *insn, *prev_jump; 666 struct instruction *insn, *prev_jump;
667 struct rela *text_rela, *rodata_rela, *prev_rela; 667 struct rela *text_rela, *rodata_rela, *prev_rela = NULL;
668 int ret; 668 int ret;
669 669
670 prev_jump = NULL; 670 prev_jump = NULL;
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5b46b1d1a37c..69966abf65d1 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -367,6 +367,28 @@ options.
367'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj 367'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj
368in config file is set to true. 368in config file is set to true.
369 369
370--tail-synthesize::
371Instead of collecting non-sample events (for example, fork, comm, mmap) at
372the beginning of record, collect them during finalizing an output file.
373The collected non-sample events reflects the status of the system when
374record is finished.
375
376--overwrite::
377Makes all events use an overwritable ring buffer. An overwritable ring
378buffer works like a flight recorder: when it gets full, the kernel will
379overwrite the oldest records, that thus will never make it to the
380perf.data file.
381
382When '--overwrite' and '--switch-output' are used perf records and drops
383events until it receives a signal, meaning that something unusual was
384detected that warrants taking a snapshot of the most current events,
385those fitting in the ring buffer at that moment.
386
387'overwrite' attribute can also be set or canceled for an event using
388config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'.
389
390Implies --tail-synthesize.
391
370SEE ALSO 392SEE ALSO
371-------- 393--------
372linkperf:perf-stat[1], linkperf:perf-list[1] 394linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d9f5cc3a3667..8f2c16d9275f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -119,11 +119,10 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
119} 119}
120 120
121static int 121static int
122rb_find_range(struct perf_evlist *evlist, 122rb_find_range(void *data, int mask, u64 head, u64 old,
123 void *data, int mask, u64 head, u64 old, 123 u64 *start, u64 *end, bool backward)
124 u64 *start, u64 *end)
125{ 124{
126 if (!evlist->backward) { 125 if (!backward) {
127 *start = old; 126 *start = old;
128 *end = head; 127 *end = head;
129 return 0; 128 return 0;
@@ -132,9 +131,10 @@ rb_find_range(struct perf_evlist *evlist,
132 return backward_rb_find_range(data, mask, head, start, end); 131 return backward_rb_find_range(data, mask, head, start, end);
133} 132}
134 133
135static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int idx) 134static int
135record__mmap_read(struct record *rec, struct perf_mmap *md,
136 bool overwrite, bool backward)
136{ 137{
137 struct perf_mmap *md = &evlist->mmap[idx];
138 u64 head = perf_mmap__read_head(md); 138 u64 head = perf_mmap__read_head(md);
139 u64 old = md->prev; 139 u64 old = md->prev;
140 u64 end = head, start = old; 140 u64 end = head, start = old;
@@ -143,8 +143,8 @@ static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int
143 void *buf; 143 void *buf;
144 int rc = 0; 144 int rc = 0;
145 145
146 if (rb_find_range(evlist, data, md->mask, head, 146 if (rb_find_range(data, md->mask, head,
147 old, &start, &end)) 147 old, &start, &end, backward))
148 return -1; 148 return -1;
149 149
150 if (start == end) 150 if (start == end)
@@ -157,7 +157,7 @@ static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int
157 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 157 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
158 158
159 md->prev = head; 159 md->prev = head;
160 perf_evlist__mmap_consume(evlist, idx); 160 perf_mmap__consume(md, overwrite || backward);
161 return 0; 161 return 0;
162 } 162 }
163 163
@@ -182,7 +182,7 @@ static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int
182 } 182 }
183 183
184 md->prev = head; 184 md->prev = head;
185 perf_evlist__mmap_consume(evlist, idx); 185 perf_mmap__consume(md, overwrite || backward);
186out: 186out:
187 return rc; 187 return rc;
188} 188}
@@ -498,20 +498,30 @@ static struct perf_event_header finished_round_event = {
498 .type = PERF_RECORD_FINISHED_ROUND, 498 .type = PERF_RECORD_FINISHED_ROUND,
499}; 499};
500 500
501static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist) 501static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
502 bool backward)
502{ 503{
503 u64 bytes_written = rec->bytes_written; 504 u64 bytes_written = rec->bytes_written;
504 int i; 505 int i;
505 int rc = 0; 506 int rc = 0;
507 struct perf_mmap *maps;
506 508
507 if (!evlist) 509 if (!evlist)
508 return 0; 510 return 0;
509 511
512 maps = backward ? evlist->backward_mmap : evlist->mmap;
513 if (!maps)
514 return 0;
515
516 if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
517 return 0;
518
510 for (i = 0; i < evlist->nr_mmaps; i++) { 519 for (i = 0; i < evlist->nr_mmaps; i++) {
511 struct auxtrace_mmap *mm = &evlist->mmap[i].auxtrace_mmap; 520 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
512 521
513 if (evlist->mmap[i].base) { 522 if (maps[i].base) {
514 if (record__mmap_read(rec, evlist, i) != 0) { 523 if (record__mmap_read(rec, &maps[i],
524 evlist->overwrite, backward) != 0) {
515 rc = -1; 525 rc = -1;
516 goto out; 526 goto out;
517 } 527 }
@@ -531,6 +541,8 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
531 if (bytes_written != rec->bytes_written) 541 if (bytes_written != rec->bytes_written)
532 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 542 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
533 543
544 if (backward)
545 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
534out: 546out:
535 return rc; 547 return rc;
536} 548}
@@ -539,11 +551,11 @@ static int record__mmap_read_all(struct record *rec)
539{ 551{
540 int err; 552 int err;
541 553
542 err = record__mmap_read_evlist(rec, rec->evlist); 554 err = record__mmap_read_evlist(rec, rec->evlist, false);
543 if (err) 555 if (err)
544 return err; 556 return err;
545 557
546 return err; 558 return record__mmap_read_evlist(rec, rec->evlist, true);
547} 559}
548 560
549static void record__init_features(struct record *rec) 561static void record__init_features(struct record *rec)
@@ -592,13 +604,16 @@ record__finish_output(struct record *rec)
592 return; 604 return;
593} 605}
594 606
595static int record__synthesize_workload(struct record *rec) 607static int record__synthesize_workload(struct record *rec, bool tail)
596{ 608{
597 struct { 609 struct {
598 struct thread_map map; 610 struct thread_map map;
599 struct thread_map_data map_data; 611 struct thread_map_data map_data;
600 } thread_map; 612 } thread_map;
601 613
614 if (rec->opts.tail_synthesize != tail)
615 return 0;
616
602 thread_map.map.nr = 1; 617 thread_map.map.nr = 1;
603 thread_map.map.map[0].pid = rec->evlist->workload.pid; 618 thread_map.map.map[0].pid = rec->evlist->workload.pid;
604 thread_map.map.map[0].comm = NULL; 619 thread_map.map.map[0].comm = NULL;
@@ -609,7 +624,7 @@ static int record__synthesize_workload(struct record *rec)
609 rec->opts.proc_map_timeout); 624 rec->opts.proc_map_timeout);
610} 625}
611 626
612static int record__synthesize(struct record *rec); 627static int record__synthesize(struct record *rec, bool tail);
613 628
614static int 629static int
615record__switch_output(struct record *rec, bool at_exit) 630record__switch_output(struct record *rec, bool at_exit)
@@ -620,6 +635,10 @@ record__switch_output(struct record *rec, bool at_exit)
620 /* Same Size: "2015122520103046"*/ 635 /* Same Size: "2015122520103046"*/
621 char timestamp[] = "InvalidTimestamp"; 636 char timestamp[] = "InvalidTimestamp";
622 637
638 record__synthesize(rec, true);
639 if (target__none(&rec->opts.target))
640 record__synthesize_workload(rec, true);
641
623 rec->samples = 0; 642 rec->samples = 0;
624 record__finish_output(rec); 643 record__finish_output(rec);
625 err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 644 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
@@ -642,7 +661,7 @@ record__switch_output(struct record *rec, bool at_exit)
642 661
643 /* Output tracking events */ 662 /* Output tracking events */
644 if (!at_exit) { 663 if (!at_exit) {
645 record__synthesize(rec); 664 record__synthesize(rec, false);
646 665
647 /* 666 /*
648 * In 'perf record --switch-output' without -a, 667 * In 'perf record --switch-output' without -a,
@@ -654,7 +673,7 @@ record__switch_output(struct record *rec, bool at_exit)
654 * perf_event__synthesize_thread_map() for those events. 673 * perf_event__synthesize_thread_map() for those events.
655 */ 674 */
656 if (target__none(&rec->opts.target)) 675 if (target__none(&rec->opts.target))
657 record__synthesize_workload(rec); 676 record__synthesize_workload(rec, false);
658 } 677 }
659 return fd; 678 return fd;
660} 679}
@@ -689,8 +708,12 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused
689static const struct perf_event_mmap_page * 708static const struct perf_event_mmap_page *
690perf_evlist__pick_pc(struct perf_evlist *evlist) 709perf_evlist__pick_pc(struct perf_evlist *evlist)
691{ 710{
692 if (evlist && evlist->mmap && evlist->mmap[0].base) 711 if (evlist) {
693 return evlist->mmap[0].base; 712 if (evlist->mmap && evlist->mmap[0].base)
713 return evlist->mmap[0].base;
714 if (evlist->backward_mmap && evlist->backward_mmap[0].base)
715 return evlist->backward_mmap[0].base;
716 }
694 return NULL; 717 return NULL;
695} 718}
696 719
@@ -704,7 +727,7 @@ static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
704 return NULL; 727 return NULL;
705} 728}
706 729
707static int record__synthesize(struct record *rec) 730static int record__synthesize(struct record *rec, bool tail)
708{ 731{
709 struct perf_session *session = rec->session; 732 struct perf_session *session = rec->session;
710 struct machine *machine = &session->machines.host; 733 struct machine *machine = &session->machines.host;
@@ -714,6 +737,9 @@ static int record__synthesize(struct record *rec)
714 int fd = perf_data_file__fd(file); 737 int fd = perf_data_file__fd(file);
715 int err = 0; 738 int err = 0;
716 739
740 if (rec->opts.tail_synthesize != tail)
741 return 0;
742
717 if (file->is_pipe) { 743 if (file->is_pipe) {
718 err = perf_event__synthesize_attrs(tool, session, 744 err = perf_event__synthesize_attrs(tool, session,
719 process_synthesized_event); 745 process_synthesized_event);
@@ -877,7 +903,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
877 903
878 machine = &session->machines.host; 904 machine = &session->machines.host;
879 905
880 err = record__synthesize(rec); 906 err = record__synthesize(rec, false);
881 if (err < 0) 907 if (err < 0)
882 goto out_child; 908 goto out_child;
883 909
@@ -937,6 +963,17 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
937 for (;;) { 963 for (;;) {
938 unsigned long long hits = rec->samples; 964 unsigned long long hits = rec->samples;
939 965
966 /*
967 * rec->evlist->bkw_mmap_state is possible to be
968 * BKW_MMAP_EMPTY here: when done == true and
969 * hits != rec->samples in previous round.
970 *
971 * perf_evlist__toggle_bkw_mmap ensure we never
972 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
973 */
974 if (trigger_is_hit(&switch_output_trigger) || done || draining)
975 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
976
940 if (record__mmap_read_all(rec) < 0) { 977 if (record__mmap_read_all(rec) < 0) {
941 trigger_error(&auxtrace_snapshot_trigger); 978 trigger_error(&auxtrace_snapshot_trigger);
942 trigger_error(&switch_output_trigger); 979 trigger_error(&switch_output_trigger);
@@ -956,8 +993,26 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
956 } 993 }
957 994
958 if (trigger_is_hit(&switch_output_trigger)) { 995 if (trigger_is_hit(&switch_output_trigger)) {
996 /*
997 * If switch_output_trigger is hit, the data in
998 * overwritable ring buffer should have been collected,
999 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
1000 *
1001 * If SIGUSR2 raise after or during record__mmap_read_all(),
1002 * record__mmap_read_all() didn't collect data from
1003 * overwritable ring buffer. Read again.
1004 */
1005 if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
1006 continue;
959 trigger_ready(&switch_output_trigger); 1007 trigger_ready(&switch_output_trigger);
960 1008
1009 /*
1010 * Reenable events in overwrite ring buffer after
1011 * record__mmap_read_all(): we should have collected
1012 * data from it.
1013 */
1014 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
1015
961 if (!quiet) 1016 if (!quiet)
962 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 1017 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
963 waking); 1018 waking);
@@ -1012,6 +1067,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
1012 if (!quiet) 1067 if (!quiet)
1013 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 1068 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
1014 1069
1070 if (target__none(&rec->opts.target))
1071 record__synthesize_workload(rec, true);
1072
1015out_child: 1073out_child:
1016 if (forks) { 1074 if (forks) {
1017 int exit_status; 1075 int exit_status;
@@ -1030,6 +1088,7 @@ out_child:
1030 } else 1088 } else
1031 status = err; 1089 status = err;
1032 1090
1091 record__synthesize(rec, true);
1033 /* this will be recalculated during process_buildids() */ 1092 /* this will be recalculated during process_buildids() */
1034 rec->samples = 0; 1093 rec->samples = 0;
1035 1094
@@ -1354,6 +1413,9 @@ struct option __record_options[] = {
1354 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1413 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1355 &record.opts.no_inherit_set, 1414 &record.opts.no_inherit_set,
1356 "child tasks do not inherit counters"), 1415 "child tasks do not inherit counters"),
1416 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1417 "synthesize non-sample events at the end of output"),
1418 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1357 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1419 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1358 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1420 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1359 "number of mmap data pages and AUX area tracing mmap pages", 1421 "number of mmap data pages and AUX area tracing mmap pages",
@@ -1564,6 +1626,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1564 } 1626 }
1565 } 1627 }
1566 1628
1629 if (record.opts.overwrite)
1630 record.opts.tail_synthesize = true;
1631
1567 if (rec->evlist->nr_entries == 0 && 1632 if (rec->evlist->nr_entries == 0 &&
1568 perf_evlist__add_default(rec->evlist) < 0) { 1633 perf_evlist__add_default(rec->evlist) < 0) {
1569 pr_err("Not enough memory for event selector list\n"); 1634 pr_err("Not enough memory for event selector list\n");
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 4b2ff021434c..64c06961bfe4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -503,7 +503,7 @@ void pthread__unblock_sigwinch(void)
503static void cache_line_size(int *cacheline_sizep) 503static void cache_line_size(int *cacheline_sizep)
504{ 504{
505 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep)) 505 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
506 perror("cannot determine cache line size"); 506 pr_debug("cannot determine cache line size");
507} 507}
508#endif 508#endif
509 509
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cd8f1b150f9e..a7e0f1497244 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -59,6 +59,8 @@ struct record_opts {
59 bool record_switch_events; 59 bool record_switch_events;
60 bool all_kernel; 60 bool all_kernel;
61 bool all_user; 61 bool all_user;
62 bool tail_synthesize;
63 bool overwrite;
62 unsigned int freq; 64 unsigned int freq;
63 unsigned int mmap_pages; 65 unsigned int mmap_pages;
64 unsigned int auxtrace_mmap_pages; 66 unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index f20ea4c0d0cb..615780cbfe1d 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -31,8 +31,8 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
31 for (i = 0; i < evlist->nr_mmaps; i++) { 31 for (i = 0; i < evlist->nr_mmaps; i++) {
32 union perf_event *event; 32 union perf_event *event;
33 33
34 perf_evlist__mmap_read_catchup(evlist, i); 34 perf_mmap__read_catchup(&evlist->backward_mmap[i]);
35 while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) { 35 while ((event = perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) {
36 const u32 type = event->header.type; 36 const u32 type = event->header.type;
37 37
38 switch (type) { 38 switch (type) {
@@ -108,7 +108,11 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
108 } 108 }
109 109
110 bzero(&parse_error, sizeof(parse_error)); 110 bzero(&parse_error, sizeof(parse_error));
111 err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error); 111 /*
112 * Set backward bit, ring buffer should be writing from end. Record
113 * it in aux evlist
114 */
115 err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error);
112 if (err) { 116 if (err) {
113 pr_debug("Failed to parse tracepoint event, try use root\n"); 117 pr_debug("Failed to parse tracepoint event, try use root\n");
114 ret = TEST_SKIP; 118 ret = TEST_SKIP;
@@ -117,10 +121,6 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
117 121
118 perf_evlist__config(evlist, &opts, NULL); 122 perf_evlist__config(evlist, &opts, NULL);
119 123
120 /* Set backward bit, ring buffer should be writing from end */
121 evlist__for_each_entry(evlist, evsel)
122 evsel->attr.write_backward = 1;
123
124 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
125 if (err < 0) { 125 if (err < 0) {
126 pr_debug("perf_evlist__open: %s\n", 126 pr_debug("perf_evlist__open: %s\n",
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 862e69c2690d..2a40b8e1def7 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -15,6 +15,7 @@
15#include "evlist.h" 15#include "evlist.h"
16#include "evsel.h" 16#include "evsel.h"
17#include "debug.h" 17#include "debug.h"
18#include "asm/bug.h"
18#include <unistd.h> 19#include <unistd.h>
19 20
20#include "parse-events.h" 21#include "parse-events.h"
@@ -27,8 +28,8 @@
27#include <linux/log2.h> 28#include <linux/log2.h>
28#include <linux/err.h> 29#include <linux/err.h>
29 30
30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 31static void perf_mmap__munmap(struct perf_mmap *map);
31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 32static void perf_mmap__put(struct perf_mmap *map);
32 33
33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 34#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 35#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
@@ -44,7 +45,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
44 perf_evlist__set_maps(evlist, cpus, threads); 45 perf_evlist__set_maps(evlist, cpus, threads);
45 fdarray__init(&evlist->pollfd, 64); 46 fdarray__init(&evlist->pollfd, 64);
46 evlist->workload.pid = -1; 47 evlist->workload.pid = -1;
47 evlist->backward = false; 48 evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
48} 49}
49 50
50struct perf_evlist *perf_evlist__new(void) 51struct perf_evlist *perf_evlist__new(void)
@@ -122,6 +123,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
122void perf_evlist__exit(struct perf_evlist *evlist) 123void perf_evlist__exit(struct perf_evlist *evlist)
123{ 124{
124 zfree(&evlist->mmap); 125 zfree(&evlist->mmap);
126 zfree(&evlist->backward_mmap);
125 fdarray__exit(&evlist->pollfd); 127 fdarray__exit(&evlist->pollfd);
126} 128}
127 129
@@ -465,7 +467,8 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
465 return 0; 467 return 0;
466} 468}
467 469
468static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx, short revent) 470static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
471 struct perf_mmap *map, short revent)
469{ 472{
470 int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP); 473 int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP);
471 /* 474 /*
@@ -473,7 +476,7 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx
473 * close the associated evlist->mmap[] entry. 476 * close the associated evlist->mmap[] entry.
474 */ 477 */
475 if (pos >= 0) { 478 if (pos >= 0) {
476 evlist->pollfd.priv[pos].idx = idx; 479 evlist->pollfd.priv[pos].ptr = map;
477 480
478 fcntl(fd, F_SETFL, O_NONBLOCK); 481 fcntl(fd, F_SETFL, O_NONBLOCK);
479 } 482 }
@@ -483,15 +486,16 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx
483 486
484int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 487int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
485{ 488{
486 return __perf_evlist__add_pollfd(evlist, fd, -1, POLLIN); 489 return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN);
487} 490}
488 491
489static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd, 492static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd,
490 void *arg __maybe_unused) 493 void *arg __maybe_unused)
491{ 494{
492 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); 495 struct perf_mmap *map = fda->priv[fd].ptr;
493 496
494 perf_evlist__mmap_put(evlist, fda->priv[fd].idx); 497 if (map)
498 perf_mmap__put(map);
495} 499}
496 500
497int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) 501int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
@@ -688,8 +692,11 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
688{ 692{
689 int i; 693 int i;
690 694
695 if (!evlist->backward_mmap)
696 return 0;
697
691 for (i = 0; i < evlist->nr_mmaps; i++) { 698 for (i = 0; i < evlist->nr_mmaps; i++) {
692 int fd = evlist->mmap[i].fd; 699 int fd = evlist->backward_mmap[i].fd;
693 int err; 700 int err;
694 701
695 if (fd < 0) 702 if (fd < 0)
@@ -701,12 +708,12 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
701 return 0; 708 return 0;
702} 709}
703 710
704int perf_evlist__pause(struct perf_evlist *evlist) 711static int perf_evlist__pause(struct perf_evlist *evlist)
705{ 712{
706 return perf_evlist__set_paused(evlist, true); 713 return perf_evlist__set_paused(evlist, true);
707} 714}
708 715
709int perf_evlist__resume(struct perf_evlist *evlist) 716static int perf_evlist__resume(struct perf_evlist *evlist)
710{ 717{
711 return perf_evlist__set_paused(evlist, false); 718 return perf_evlist__set_paused(evlist, false);
712} 719}
@@ -781,9 +788,8 @@ broken_event:
781 return event; 788 return event;
782} 789}
783 790
784union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx) 791union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup)
785{ 792{
786 struct perf_mmap *md = &evlist->mmap[idx];
787 u64 head; 793 u64 head;
788 u64 old = md->prev; 794 u64 old = md->prev;
789 795
@@ -795,13 +801,12 @@ union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int
795 801
796 head = perf_mmap__read_head(md); 802 head = perf_mmap__read_head(md);
797 803
798 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); 804 return perf_mmap__read(md, check_messup, old, head, &md->prev);
799} 805}
800 806
801union perf_event * 807union perf_event *
802perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) 808perf_mmap__read_backward(struct perf_mmap *md)
803{ 809{
804 struct perf_mmap *md = &evlist->mmap[idx];
805 u64 head, end; 810 u64 head, end;
806 u64 start = md->prev; 811 u64 start = md->prev;
807 812
@@ -836,16 +841,38 @@ perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
836 return perf_mmap__read(md, false, start, end, &md->prev); 841 return perf_mmap__read(md, false, start, end, &md->prev);
837} 842}
838 843
839union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 844union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
840{ 845{
841 if (!evlist->backward) 846 struct perf_mmap *md = &evlist->mmap[idx];
842 return perf_evlist__mmap_read_forward(evlist, idx); 847
843 return perf_evlist__mmap_read_backward(evlist, idx); 848 /*
849 * Check messup is required for forward overwritable ring buffer:
850 * memory pointed by md->prev can be overwritten in this case.
851 * No need for read-write ring buffer: kernel stop outputting when
852 * it hit md->prev (perf_mmap__consume()).
853 */
854 return perf_mmap__read_forward(md, evlist->overwrite);
844} 855}
845 856
846void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) 857union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
847{ 858{
848 struct perf_mmap *md = &evlist->mmap[idx]; 859 struct perf_mmap *md = &evlist->mmap[idx];
860
861 /*
862 * No need to check messup for backward ring buffer:
863 * We can always read arbitrary long data from a backward
864 * ring buffer unless we forget to pause it before reading.
865 */
866 return perf_mmap__read_backward(md);
867}
868
869union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
870{
871 return perf_evlist__mmap_read_forward(evlist, idx);
872}
873
874void perf_mmap__read_catchup(struct perf_mmap *md)
875{
849 u64 head; 876 u64 head;
850 877
851 if (!atomic_read(&md->refcnt)) 878 if (!atomic_read(&md->refcnt))
@@ -855,38 +882,44 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
855 md->prev = head; 882 md->prev = head;
856} 883}
857 884
885void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
886{
887 perf_mmap__read_catchup(&evlist->mmap[idx]);
888}
889
858static bool perf_mmap__empty(struct perf_mmap *md) 890static bool perf_mmap__empty(struct perf_mmap *md)
859{ 891{
860 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 892 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
861} 893}
862 894
863static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 895static void perf_mmap__get(struct perf_mmap *map)
864{ 896{
865 atomic_inc(&evlist->mmap[idx].refcnt); 897 atomic_inc(&map->refcnt);
866} 898}
867 899
868static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) 900static void perf_mmap__put(struct perf_mmap *md)
869{ 901{
870 struct perf_mmap *md = &evlist->mmap[idx];
871
872 BUG_ON(md->base && atomic_read(&md->refcnt) == 0); 902 BUG_ON(md->base && atomic_read(&md->refcnt) == 0);
873 903
874 if (atomic_dec_and_test(&md->refcnt)) 904 if (atomic_dec_and_test(&md->refcnt))
875 __perf_evlist__munmap(evlist, idx); 905 perf_mmap__munmap(md);
876} 906}
877 907
878void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 908void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
879{ 909{
880 struct perf_mmap *md = &evlist->mmap[idx]; 910 if (!overwrite) {
881
882 if (!evlist->overwrite) {
883 u64 old = md->prev; 911 u64 old = md->prev;
884 912
885 perf_mmap__write_tail(md, old); 913 perf_mmap__write_tail(md, old);
886 } 914 }
887 915
888 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) 916 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
889 perf_evlist__mmap_put(evlist, idx); 917 perf_mmap__put(md);
918}
919
920void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
921{
922 perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
890} 923}
891 924
892int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, 925int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
@@ -917,44 +950,52 @@ void __weak auxtrace_mmap_params__set_idx(
917{ 950{
918} 951}
919 952
920static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 953static void perf_mmap__munmap(struct perf_mmap *map)
921{ 954{
922 if (evlist->mmap[idx].base != NULL) { 955 if (map->base != NULL) {
923 munmap(evlist->mmap[idx].base, evlist->mmap_len); 956 munmap(map->base, perf_mmap__mmap_len(map));
924 evlist->mmap[idx].base = NULL; 957 map->base = NULL;
925 evlist->mmap[idx].fd = -1; 958 map->fd = -1;
926 atomic_set(&evlist->mmap[idx].refcnt, 0); 959 atomic_set(&map->refcnt, 0);
927 } 960 }
928 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); 961 auxtrace_mmap__munmap(&map->auxtrace_mmap);
929} 962}
930 963
931void perf_evlist__munmap(struct perf_evlist *evlist) 964static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
932{ 965{
933 int i; 966 int i;
934 967
935 if (evlist->mmap == NULL) 968 if (evlist->mmap)
936 return; 969 for (i = 0; i < evlist->nr_mmaps; i++)
970 perf_mmap__munmap(&evlist->mmap[i]);
937 971
938 for (i = 0; i < evlist->nr_mmaps; i++) 972 if (evlist->backward_mmap)
939 __perf_evlist__munmap(evlist, i); 973 for (i = 0; i < evlist->nr_mmaps; i++)
974 perf_mmap__munmap(&evlist->backward_mmap[i]);
975}
940 976
977void perf_evlist__munmap(struct perf_evlist *evlist)
978{
979 perf_evlist__munmap_nofree(evlist);
941 zfree(&evlist->mmap); 980 zfree(&evlist->mmap);
981 zfree(&evlist->backward_mmap);
942} 982}
943 983
944static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 984static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
945{ 985{
946 int i; 986 int i;
987 struct perf_mmap *map;
947 988
948 evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 989 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
949 if (cpu_map__empty(evlist->cpus)) 990 if (cpu_map__empty(evlist->cpus))
950 evlist->nr_mmaps = thread_map__nr(evlist->threads); 991 evlist->nr_mmaps = thread_map__nr(evlist->threads);
951 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 992 map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
952 if (!evlist->mmap) 993 if (!map)
953 return -ENOMEM; 994 return NULL;
954 995
955 for (i = 0; i < evlist->nr_mmaps; i++) 996 for (i = 0; i < evlist->nr_mmaps; i++)
956 evlist->mmap[i].fd = -1; 997 map[i].fd = -1;
957 return 0; 998 return map;
958} 999}
959 1000
960struct mmap_params { 1001struct mmap_params {
@@ -963,8 +1004,8 @@ struct mmap_params {
963 struct auxtrace_mmap_params auxtrace_mp; 1004 struct auxtrace_mmap_params auxtrace_mp;
964}; 1005};
965 1006
966static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 1007static int perf_mmap__mmap(struct perf_mmap *map,
967 struct mmap_params *mp, int fd) 1008 struct mmap_params *mp, int fd)
968{ 1009{
969 /* 1010 /*
970 * The last one will be done at perf_evlist__mmap_consume(), so that we 1011 * The last one will be done at perf_evlist__mmap_consume(), so that we
@@ -979,21 +1020,21 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
979 * evlist layer can't just drop it when filtering events in 1020 * evlist layer can't just drop it when filtering events in
980 * perf_evlist__filter_pollfd(). 1021 * perf_evlist__filter_pollfd().
981 */ 1022 */
982 atomic_set(&evlist->mmap[idx].refcnt, 2); 1023 atomic_set(&map->refcnt, 2);
983 evlist->mmap[idx].prev = 0; 1024 map->prev = 0;
984 evlist->mmap[idx].mask = mp->mask; 1025 map->mask = mp->mask;
985 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 1026 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
986 MAP_SHARED, fd, 0); 1027 MAP_SHARED, fd, 0);
987 if (evlist->mmap[idx].base == MAP_FAILED) { 1028 if (map->base == MAP_FAILED) {
988 pr_debug2("failed to mmap perf event ring buffer, error %d\n", 1029 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
989 errno); 1030 errno);
990 evlist->mmap[idx].base = NULL; 1031 map->base = NULL;
991 return -1; 1032 return -1;
992 } 1033 }
993 evlist->mmap[idx].fd = fd; 1034 map->fd = fd;
994 1035
995 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, 1036 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
996 &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) 1037 &mp->auxtrace_mp, map->base, fd))
997 return -1; 1038 return -1;
998 1039
999 return 0; 1040 return 0;
@@ -1003,23 +1044,36 @@ static bool
1003perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, 1044perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
1004 struct perf_evsel *evsel) 1045 struct perf_evsel *evsel)
1005{ 1046{
1006 if (evsel->overwrite) 1047 if (evsel->attr.write_backward)
1007 return false; 1048 return false;
1008 return true; 1049 return true;
1009} 1050}
1010 1051
1011static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 1052static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1012 struct mmap_params *mp, int cpu, 1053 struct mmap_params *mp, int cpu,
1013 int thread, int *output) 1054 int thread, int *_output, int *_output_backward)
1014{ 1055{
1015 struct perf_evsel *evsel; 1056 struct perf_evsel *evsel;
1016 int revent; 1057 int revent;
1017 1058
1018 evlist__for_each_entry(evlist, evsel) { 1059 evlist__for_each_entry(evlist, evsel) {
1060 struct perf_mmap *maps = evlist->mmap;
1061 int *output = _output;
1019 int fd; 1062 int fd;
1020 1063
1021 if (evsel->overwrite != (evlist->overwrite && evlist->backward)) 1064 if (evsel->attr.write_backward) {
1022 continue; 1065 output = _output_backward;
1066 maps = evlist->backward_mmap;
1067
1068 if (!maps) {
1069 maps = perf_evlist__alloc_mmap(evlist);
1070 if (!maps)
1071 return -1;
1072 evlist->backward_mmap = maps;
1073 if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
1074 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
1075 }
1076 }
1023 1077
1024 if (evsel->system_wide && thread) 1078 if (evsel->system_wide && thread)
1025 continue; 1079 continue;
@@ -1028,13 +1082,14 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1028 1082
1029 if (*output == -1) { 1083 if (*output == -1) {
1030 *output = fd; 1084 *output = fd;
1031 if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) 1085
1086 if (perf_mmap__mmap(&maps[idx], mp, *output) < 0)
1032 return -1; 1087 return -1;
1033 } else { 1088 } else {
1034 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 1089 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
1035 return -1; 1090 return -1;
1036 1091
1037 perf_evlist__mmap_get(evlist, idx); 1092 perf_mmap__get(&maps[idx]);
1038 } 1093 }
1039 1094
1040 revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0; 1095 revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0;
@@ -1047,8 +1102,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1047 * Therefore don't add it for polling. 1102 * Therefore don't add it for polling.
1048 */ 1103 */
1049 if (!evsel->system_wide && 1104 if (!evsel->system_wide &&
1050 __perf_evlist__add_pollfd(evlist, fd, idx, revent) < 0) { 1105 __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) {
1051 perf_evlist__mmap_put(evlist, idx); 1106 perf_mmap__put(&maps[idx]);
1052 return -1; 1107 return -1;
1053 } 1108 }
1054 1109
@@ -1074,13 +1129,14 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
1074 pr_debug2("perf event ring buffer mmapped per cpu\n"); 1129 pr_debug2("perf event ring buffer mmapped per cpu\n");
1075 for (cpu = 0; cpu < nr_cpus; cpu++) { 1130 for (cpu = 0; cpu < nr_cpus; cpu++) {
1076 int output = -1; 1131 int output = -1;
1132 int output_backward = -1;
1077 1133
1078 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, 1134 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
1079 true); 1135 true);
1080 1136
1081 for (thread = 0; thread < nr_threads; thread++) { 1137 for (thread = 0; thread < nr_threads; thread++) {
1082 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 1138 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
1083 thread, &output)) 1139 thread, &output, &output_backward))
1084 goto out_unmap; 1140 goto out_unmap;
1085 } 1141 }
1086 } 1142 }
@@ -1088,8 +1144,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
1088 return 0; 1144 return 0;
1089 1145
1090out_unmap: 1146out_unmap:
1091 for (cpu = 0; cpu < nr_cpus; cpu++) 1147 perf_evlist__munmap_nofree(evlist);
1092 __perf_evlist__munmap(evlist, cpu);
1093 return -1; 1148 return -1;
1094} 1149}
1095 1150
@@ -1102,20 +1157,20 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
1102 pr_debug2("perf event ring buffer mmapped per thread\n"); 1157 pr_debug2("perf event ring buffer mmapped per thread\n");
1103 for (thread = 0; thread < nr_threads; thread++) { 1158 for (thread = 0; thread < nr_threads; thread++) {
1104 int output = -1; 1159 int output = -1;
1160 int output_backward = -1;
1105 1161
1106 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, 1162 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
1107 false); 1163 false);
1108 1164
1109 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 1165 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
1110 &output)) 1166 &output, &output_backward))
1111 goto out_unmap; 1167 goto out_unmap;
1112 } 1168 }
1113 1169
1114 return 0; 1170 return 0;
1115 1171
1116out_unmap: 1172out_unmap:
1117 for (thread = 0; thread < nr_threads; thread++) 1173 perf_evlist__munmap_nofree(evlist);
1118 __perf_evlist__munmap(evlist, thread);
1119 return -1; 1174 return -1;
1120} 1175}
1121 1176
@@ -1248,7 +1303,9 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1248 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), 1303 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
1249 }; 1304 };
1250 1305
1251 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 1306 if (!evlist->mmap)
1307 evlist->mmap = perf_evlist__alloc_mmap(evlist);
1308 if (!evlist->mmap)
1252 return -ENOMEM; 1309 return -ENOMEM;
1253 1310
1254 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 1311 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
@@ -1919,3 +1976,61 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
1919 1976
1920 return NULL; 1977 return NULL;
1921} 1978}
1979
1980void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
1981 enum bkw_mmap_state state)
1982{
1983 enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
1984 enum action {
1985 NONE,
1986 PAUSE,
1987 RESUME,
1988 } action = NONE;
1989
1990 if (!evlist->backward_mmap)
1991 return;
1992
1993 switch (old_state) {
1994 case BKW_MMAP_NOTREADY: {
1995 if (state != BKW_MMAP_RUNNING)
1996 goto state_err;;
1997 break;
1998 }
1999 case BKW_MMAP_RUNNING: {
2000 if (state != BKW_MMAP_DATA_PENDING)
2001 goto state_err;
2002 action = PAUSE;
2003 break;
2004 }
2005 case BKW_MMAP_DATA_PENDING: {
2006 if (state != BKW_MMAP_EMPTY)
2007 goto state_err;
2008 break;
2009 }
2010 case BKW_MMAP_EMPTY: {
2011 if (state != BKW_MMAP_RUNNING)
2012 goto state_err;
2013 action = RESUME;
2014 break;
2015 }
2016 default:
2017 WARN_ONCE(1, "Shouldn't get there\n");
2018 }
2019
2020 evlist->bkw_mmap_state = state;
2021
2022 switch (action) {
2023 case PAUSE:
2024 perf_evlist__pause(evlist);
2025 break;
2026 case RESUME:
2027 perf_evlist__resume(evlist);
2028 break;
2029 case NONE:
2030 default:
2031 break;
2032 }
2033
2034state_err:
2035 return;
2036}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index afd087761a47..4fd034f22d2f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -35,6 +35,40 @@ struct perf_mmap {
35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
36}; 36};
37 37
38static inline size_t
39perf_mmap__mmap_len(struct perf_mmap *map)
40{
41 return map->mask + 1 + page_size;
42}
43
44/*
45 * State machine of bkw_mmap_state:
46 *
47 * .________________(forbid)_____________.
48 * | V
49 * NOTREADY --(0)--> RUNNING --(1)--> DATA_PENDING --(2)--> EMPTY
50 * ^ ^ | ^ |
51 * | |__(forbid)____/ |___(forbid)___/|
52 * | |
53 * \_________________(3)_______________/
54 *
55 * NOTREADY : Backward ring buffers are not ready
56 * RUNNING : Backward ring buffers are recording
57 * DATA_PENDING : We are required to collect data from backward ring buffers
58 * EMPTY : We have collected data from backward ring buffers.
59 *
60 * (0): Setup backward ring buffer
61 * (1): Pause ring buffers for reading
62 * (2): Read from ring buffers
63 * (3): Resume ring buffers for recording
64 */
65enum bkw_mmap_state {
66 BKW_MMAP_NOTREADY,
67 BKW_MMAP_RUNNING,
68 BKW_MMAP_DATA_PENDING,
69 BKW_MMAP_EMPTY,
70};
71
38struct perf_evlist { 72struct perf_evlist {
39 struct list_head entries; 73 struct list_head entries;
40 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 74 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -44,17 +78,18 @@ struct perf_evlist {
44 bool overwrite; 78 bool overwrite;
45 bool enabled; 79 bool enabled;
46 bool has_user_cpus; 80 bool has_user_cpus;
47 bool backward;
48 size_t mmap_len; 81 size_t mmap_len;
49 int id_pos; 82 int id_pos;
50 int is_pos; 83 int is_pos;
51 u64 combined_sample_type; 84 u64 combined_sample_type;
85 enum bkw_mmap_state bkw_mmap_state;
52 struct { 86 struct {
53 int cork_fd; 87 int cork_fd;
54 pid_t pid; 88 pid_t pid;
55 } workload; 89 } workload;
56 struct fdarray pollfd; 90 struct fdarray pollfd;
57 struct perf_mmap *mmap; 91 struct perf_mmap *mmap;
92 struct perf_mmap *backward_mmap;
58 struct thread_map *threads; 93 struct thread_map *threads;
59 struct cpu_map *cpus; 94 struct cpu_map *cpus;
60 struct perf_evsel *selected; 95 struct perf_evsel *selected;
@@ -129,6 +164,14 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
129 164
130struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 165struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
131 166
167void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
168
169union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup);
170union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
171
172void perf_mmap__read_catchup(struct perf_mmap *md);
173void perf_mmap__consume(struct perf_mmap *md, bool overwrite);
174
132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 175union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
133 176
134union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, 177union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
@@ -139,8 +182,6 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
139 182
140void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 183void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
141 184
142int perf_evlist__pause(struct perf_evlist *evlist);
143int perf_evlist__resume(struct perf_evlist *evlist);
144int perf_evlist__open(struct perf_evlist *evlist); 185int perf_evlist__open(struct perf_evlist *evlist);
145void perf_evlist__close(struct perf_evlist *evlist); 186void perf_evlist__close(struct perf_evlist *evlist);
146 187
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ba0f59fa3d5d..8c54df61fe64 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -695,6 +695,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
695 */ 695 */
696 attr->inherit = term->val.inherit ? 1 : 0; 696 attr->inherit = term->val.inherit ? 1 : 0;
697 break; 697 break;
698 case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
699 attr->write_backward = term->val.overwrite ? 1 : 0;
700 break;
698 default: 701 default:
699 break; 702 break;
700 } 703 }
@@ -776,6 +779,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
776 779
777 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 780 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
778 attr->inherit = !opts->no_inherit; 781 attr->inherit = !opts->no_inherit;
782 attr->write_backward = opts->overwrite ? 1 : 0;
779 783
780 perf_evsel__set_sample_bit(evsel, IP); 784 perf_evsel__set_sample_bit(evsel, IP);
781 perf_evsel__set_sample_bit(evsel, TID); 785 perf_evsel__set_sample_bit(evsel, TID);
@@ -1377,6 +1381,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1377 int pid = -1, err; 1381 int pid = -1, err;
1378 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1382 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1379 1383
1384 if (perf_missing_features.write_backward && evsel->attr.write_backward)
1385 return -EINVAL;
1386
1380 if (evsel->system_wide) 1387 if (evsel->system_wide)
1381 nthreads = 1; 1388 nthreads = 1;
1382 else 1389 else
@@ -1407,11 +1414,6 @@ fallback_missing_features:
1407 if (perf_missing_features.lbr_flags) 1414 if (perf_missing_features.lbr_flags)
1408 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1415 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1409 PERF_SAMPLE_BRANCH_NO_CYCLES); 1416 PERF_SAMPLE_BRANCH_NO_CYCLES);
1410 if (perf_missing_features.write_backward) {
1411 if (evsel->overwrite)
1412 return -EINVAL;
1413 evsel->attr.write_backward = false;
1414 }
1415retry_sample_id: 1417retry_sample_id:
1416 if (perf_missing_features.sample_id_all) 1418 if (perf_missing_features.sample_id_all)
1417 evsel->attr.sample_id_all = 0; 1419 evsel->attr.sample_id_all = 0;
@@ -1513,7 +1515,7 @@ try_fallback:
1513 */ 1515 */
1514 if (!perf_missing_features.write_backward && evsel->attr.write_backward) { 1516 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1515 perf_missing_features.write_backward = true; 1517 perf_missing_features.write_backward = true;
1516 goto fallback_missing_features; 1518 goto out_close;
1517 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1519 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1518 perf_missing_features.clockid_wrong = true; 1520 perf_missing_features.clockid_wrong = true;
1519 goto fallback_missing_features; 1521 goto fallback_missing_features;
@@ -2422,7 +2424,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2422 "We found oprofile daemon running, please stop it and try again."); 2424 "We found oprofile daemon running, please stop it and try again.");
2423 break; 2425 break;
2424 case EINVAL: 2426 case EINVAL:
2425 if (evsel->overwrite && perf_missing_features.write_backward) 2427 if (evsel->attr.write_backward && perf_missing_features.write_backward)
2426 return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel."); 2428 return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
2427 if (perf_missing_features.clockid) 2429 if (perf_missing_features.clockid)
2428 return scnprintf(msg, size, "clockid feature not supported."); 2430 return scnprintf(msg, size, "clockid feature not supported.");
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d73391e8740e..8a4a6c9f1480 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -45,6 +45,7 @@ enum {
45 PERF_EVSEL__CONFIG_TERM_STACK_USER, 45 PERF_EVSEL__CONFIG_TERM_STACK_USER,
46 PERF_EVSEL__CONFIG_TERM_INHERIT, 46 PERF_EVSEL__CONFIG_TERM_INHERIT,
47 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 47 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
48 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
48 PERF_EVSEL__CONFIG_TERM_MAX, 49 PERF_EVSEL__CONFIG_TERM_MAX,
49}; 50};
50 51
@@ -59,6 +60,7 @@ struct perf_evsel_config_term {
59 u64 stack_user; 60 u64 stack_user;
60 int max_stack; 61 int max_stack;
61 bool inherit; 62 bool inherit;
63 bool overwrite;
62 } val; 64 } val;
63}; 65};
64 66
@@ -114,7 +116,6 @@ struct perf_evsel {
114 bool tracking; 116 bool tracking;
115 bool per_pkg; 117 bool per_pkg;
116 bool precise_max; 118 bool precise_max;
117 bool overwrite;
118 /* parse modifier helper */ 119 /* parse modifier helper */
119 int exclude_GH; 120 int exclude_GH;
120 int nr_members; 121 int nr_members;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 375af0e02831..6c913c3914fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -902,6 +902,8 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
902 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 902 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
903 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 903 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
905}; 907};
906 908
907static bool config_term_shrinked; 909static bool config_term_shrinked;
@@ -994,6 +996,12 @@ do { \
994 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 996 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
995 CHECK_TYPE_VAL(NUM); 997 CHECK_TYPE_VAL(NUM);
996 break; 998 break;
999 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1000 CHECK_TYPE_VAL(NUM);
1001 break;
1002 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1003 CHECK_TYPE_VAL(NUM);
1004 break;
997 case PARSE_EVENTS__TERM_TYPE_NAME: 1005 case PARSE_EVENTS__TERM_TYPE_NAME:
998 CHECK_TYPE_VAL(STR); 1006 CHECK_TYPE_VAL(STR);
999 break; 1007 break;
@@ -1046,6 +1054,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
1046 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1054 case PARSE_EVENTS__TERM_TYPE_INHERIT:
1047 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1055 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1048 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1056 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1057 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1058 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1049 return config_term_common(attr, term, err); 1059 return config_term_common(attr, term, err);
1050 default: 1060 default:
1051 if (err) { 1061 if (err) {
@@ -1118,6 +1128,12 @@ do { \
1118 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1128 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1119 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); 1129 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
1120 break; 1130 break;
1131 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1132 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
1133 break;
1134 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1135 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
1136 break;
1121 default: 1137 default:
1122 break; 1138 break;
1123 } 1139 }
@@ -2412,9 +2428,9 @@ static void config_terms_list(char *buf, size_t buf_sz)
2412char *parse_events_formats_error_string(char *additional_terms) 2428char *parse_events_formats_error_string(char *additional_terms)
2413{ 2429{
2414 char *str; 2430 char *str;
2415 /* "branch_type" is the longest name */ 2431 /* "no-overwrite" is the longest name */
2416 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 2432 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
2417 (sizeof("branch_type") - 1)]; 2433 (sizeof("no-overwrite") - 1)];
2418 2434
2419 config_terms_list(static_terms, sizeof(static_terms)); 2435 config_terms_list(static_terms, sizeof(static_terms));
2420 /* valid terms */ 2436 /* valid terms */
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index b4aa7eb2df73..d1edbf8cc66a 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -69,6 +69,8 @@ enum {
69 PARSE_EVENTS__TERM_TYPE_NOINHERIT, 69 PARSE_EVENTS__TERM_TYPE_NOINHERIT,
70 PARSE_EVENTS__TERM_TYPE_INHERIT, 70 PARSE_EVENTS__TERM_TYPE_INHERIT,
71 PARSE_EVENTS__TERM_TYPE_MAX_STACK, 71 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
73 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
72 __PARSE_EVENTS__TERM_TYPE_NR, 74 __PARSE_EVENTS__TERM_TYPE_NR,
73}; 75};
74 76
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 3c15b33b2e84..7a2519435da0 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -202,6 +202,8 @@ stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
202max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } 202max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
203inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 203inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
204no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 204no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
205overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
206no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
205, { return ','; } 207, { return ','; }
206"/" { BEGIN(INITIAL); return '/'; } 208"/" { BEGIN(INITIAL); return '/'; }
207{name_minus} { return str(yyscanner, PE_NAME); } 209{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 078d49626494..5d61242a6e64 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1499,10 +1499,27 @@ int perf_session__register_idle_thread(struct perf_session *session)
1499 return err; 1499 return err;
1500} 1500}
1501 1501
1502static void
1503perf_session__warn_order(const struct perf_session *session)
1504{
1505 const struct ordered_events *oe = &session->ordered_events;
1506 struct perf_evsel *evsel;
1507 bool should_warn = true;
1508
1509 evlist__for_each_entry(session->evlist, evsel) {
1510 if (evsel->attr.write_backward)
1511 should_warn = false;
1512 }
1513
1514 if (!should_warn)
1515 return;
1516 if (oe->nr_unordered_events != 0)
1517 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1518}
1519
1502static void perf_session__warn_about_errors(const struct perf_session *session) 1520static void perf_session__warn_about_errors(const struct perf_session *session)
1503{ 1521{
1504 const struct events_stats *stats = &session->evlist->stats; 1522 const struct events_stats *stats = &session->evlist->stats;
1505 const struct ordered_events *oe = &session->ordered_events;
1506 1523
1507 if (session->tool->lost == perf_event__process_lost && 1524 if (session->tool->lost == perf_event__process_lost &&
1508 stats->nr_events[PERF_RECORD_LOST] != 0) { 1525 stats->nr_events[PERF_RECORD_LOST] != 0) {
@@ -1559,8 +1576,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1559 stats->nr_unprocessable_samples); 1576 stats->nr_unprocessable_samples);
1560 } 1577 }
1561 1578
1562 if (oe->nr_unordered_events != 0) 1579 perf_session__warn_order(session);
1563 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1564 1580
1565 events_stats__auxtrace_error_warn(stats); 1581 events_stats__auxtrace_error_warn(stats);
1566 1582
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5854b4660a49..947d21f38398 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2381,6 +2381,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2381 if (sort__mode != SORT_MODE__MEMORY) 2381 if (sort__mode != SORT_MODE__MEMORY)
2382 return -EINVAL; 2382 return -EINVAL;
2383 2383
2384 if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0)
2385 return -EINVAL;
2386
2384 if (sd->entry == &sort_mem_daddr_sym) 2387 if (sd->entry == &sort_mem_daddr_sym)
2385 list->sym = 1; 2388 list->sym = 1;
2386 2389
@@ -2424,7 +2427,10 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
2424 if (*tok) { 2427 if (*tok) {
2425 ret = sort_dimension__add(list, tok, evlist, level); 2428 ret = sort_dimension__add(list, tok, evlist, level);
2426 if (ret == -EINVAL) { 2429 if (ret == -EINVAL) {
2427 error("Invalid --sort key: `%s'", tok); 2430 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok)))
2431 error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
2432 else
2433 error("Invalid --sort key: `%s'", tok);
2428 break; 2434 break;
2429 } else if (ret == -ESRCH) { 2435 } else if (ret == -ESRCH) {
2430 error("Unknown --sort key: `%s'", tok); 2436 error("Unknown --sort key: `%s'", tok);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 6178cab82374..843cbba8f9d3 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -360,7 +360,7 @@ void print_binary(unsigned char *data, size_t len,
360 size_t bytes_per_line, print_binary_t printer, 360 size_t bytes_per_line, print_binary_t printer,
361 void *extra); 361 void *extra);
362 362
363#ifndef __GLIBC__ 363#if !defined(__GLIBC__) && !defined(__ANDROID__)
364extern int sched_getcpu(void); 364extern int sched_getcpu(void);
365#endif 365#endif
366 366