diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-04-01 03:55:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-04-01 03:55:17 -0400 |
commit | aaa9fa387541a30f6f4138bea6e082319de5e3fe (patch) | |
tree | 43905494fe3c7724b8fe4326a4e820e897e7a7e9 | |
parent | ccd41c86ad4d464d0ed4e48d80759ff85c2115b0 (diff) | |
parent | 9870d7809575515e26194f4b3df1750872a6ee60 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Fix 'perf script' pipe mode segfault, by always initializing ordered_events in
perf_session__new(). (Arnaldo Carvalho de Melo)
- Fix ppid for synthesized fork events. (David Ahern)
- Fix kernel symbol resolution of callchains in S/390 by remembering the
cpumode. (David Hildenbrand)
Infrastructure changes:
- Disable libbabeltrace check by default in the build system. (Jiri Olsa)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/Makefile.perf | 2 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 5 | ||||
-rw-r--r-- | tools/perf/util/event.c | 147 | ||||
-rw-r--r-- | tools/perf/util/event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 28 | ||||
-rw-r--r-- | tools/perf/util/ordered-events.c | 21 | ||||
-rw-r--r-- | tools/perf/util/ordered-events.h | 14 | ||||
-rw-r--r-- | tools/perf/util/session.c | 48 | ||||
-rw-r--r-- | tools/perf/util/session.h | 1 |
9 files changed, 144 insertions, 123 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index e9925e6ad1d0..c43a20517591 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -69,7 +69,7 @@ include config/utilities.mak | |||
69 | # | 69 | # |
70 | # Define NO_ZLIB if you do not want to support compressed kernel modules | 70 | # Define NO_ZLIB if you do not want to support compressed kernel modules |
71 | # | 71 | # |
72 | # Define NO_LIBBABELTRACE if you do not want libbabeltrace support | 72 | # Define LIBBABELTRACE if you DO want libbabeltrace support |
73 | # for CTF data format. | 73 | # for CTF data format. |
74 | # | 74 | # |
75 | # Define NO_LZMA if you do not want to support compressed (xz) kernel modules | 75 | # Define NO_LZMA if you do not want to support compressed (xz) kernel modules |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index cd121dfc4de9..59a98c643240 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -95,7 +95,7 @@ ifndef NO_LIBELF | |||
95 | FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw | 95 | FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw |
96 | endif | 96 | endif |
97 | 97 | ||
98 | ifndef NO_LIBBABELTRACE | 98 | ifdef LIBBABELTRACE |
99 | # for linking with debug library, run like: | 99 | # for linking with debug library, run like: |
100 | # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ | 100 | # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ |
101 | ifdef LIBBABELTRACE_DIR | 101 | ifdef LIBBABELTRACE_DIR |
@@ -598,7 +598,7 @@ else | |||
598 | NO_PERF_READ_VDSOX32 := 1 | 598 | NO_PERF_READ_VDSOX32 := 1 |
599 | endif | 599 | endif |
600 | 600 | ||
601 | ifndef NO_LIBBABELTRACE | 601 | ifdef LIBBABELTRACE |
602 | $(call feature_check,libbabeltrace) | 602 | $(call feature_check,libbabeltrace) |
603 | ifeq ($(feature-libbabeltrace), 1) | 603 | ifeq ($(feature-libbabeltrace), 1) |
604 | CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS) | 604 | CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS) |
@@ -607,7 +607,6 @@ ifndef NO_LIBBABELTRACE | |||
607 | $(call detected,CONFIG_LIBBABELTRACE) | 607 | $(call detected,CONFIG_LIBBABELTRACE) |
608 | else | 608 | else |
609 | msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev); | 609 | msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev); |
610 | NO_LIBBABELTRACE := 1 | ||
611 | endif | 610 | endif |
612 | endif | 611 | endif |
613 | 612 | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d5efa5092ce6..5516236df6ab 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -49,70 +49,103 @@ static struct perf_sample synth_sample = { | |||
49 | .period = 1, | 49 | .period = 1, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | 52 | /* |
53 | * Assumes that the first 4095 bytes of /proc/pid/stat contains | ||
54 | * the comm, tgid and ppid. | ||
55 | */ | ||
56 | static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len, | ||
57 | pid_t *tgid, pid_t *ppid) | ||
53 | { | 58 | { |
54 | char filename[PATH_MAX]; | 59 | char filename[PATH_MAX]; |
55 | char bf[BUFSIZ]; | 60 | char bf[4096]; |
56 | FILE *fp; | 61 | int fd; |
57 | size_t size = 0; | 62 | size_t size = 0, n; |
58 | pid_t tgid = -1; | 63 | char *nl, *name, *tgids, *ppids; |
64 | |||
65 | *tgid = -1; | ||
66 | *ppid = -1; | ||
59 | 67 | ||
60 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | 68 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); |
61 | 69 | ||
62 | fp = fopen(filename, "r"); | 70 | fd = open(filename, O_RDONLY); |
63 | if (fp == NULL) { | 71 | if (fd < 0) { |
64 | pr_debug("couldn't open %s\n", filename); | 72 | pr_debug("couldn't open %s\n", filename); |
65 | return 0; | 73 | return -1; |
66 | } | 74 | } |
67 | 75 | ||
68 | while (!comm[0] || (tgid < 0)) { | 76 | n = read(fd, bf, sizeof(bf) - 1); |
69 | if (fgets(bf, sizeof(bf), fp) == NULL) { | 77 | close(fd); |
70 | pr_warning("couldn't get COMM and pgid, malformed %s\n", | 78 | if (n <= 0) { |
71 | filename); | 79 | pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n", |
72 | break; | 80 | pid); |
73 | } | 81 | return -1; |
82 | } | ||
83 | bf[n] = '\0'; | ||
74 | 84 | ||
75 | if (memcmp(bf, "Name:", 5) == 0) { | 85 | name = strstr(bf, "Name:"); |
76 | char *name = bf + 5; | 86 | tgids = strstr(bf, "Tgid:"); |
77 | while (*name && isspace(*name)) | 87 | ppids = strstr(bf, "PPid:"); |
78 | ++name; | 88 | |
79 | size = strlen(name) - 1; | 89 | if (name) { |
80 | if (size >= len) | 90 | name += 5; /* strlen("Name:") */ |
81 | size = len - 1; | 91 | |
82 | memcpy(comm, name, size); | 92 | while (*name && isspace(*name)) |
83 | comm[size] = '\0'; | 93 | ++name; |
84 | 94 | ||
85 | } else if (memcmp(bf, "Tgid:", 5) == 0) { | 95 | nl = strchr(name, '\n'); |
86 | char *tgids = bf + 5; | 96 | if (nl) |
87 | while (*tgids && isspace(*tgids)) | 97 | *nl = '\0'; |
88 | ++tgids; | 98 | |
89 | tgid = atoi(tgids); | 99 | size = strlen(name); |
90 | } | 100 | if (size >= len) |
101 | size = len - 1; | ||
102 | memcpy(comm, name, size); | ||
103 | comm[size] = '\0'; | ||
104 | } else { | ||
105 | pr_debug("Name: string not found for pid %d\n", pid); | ||
91 | } | 106 | } |
92 | 107 | ||
93 | fclose(fp); | 108 | if (tgids) { |
109 | tgids += 5; /* strlen("Tgid:") */ | ||
110 | *tgid = atoi(tgids); | ||
111 | } else { | ||
112 | pr_debug("Tgid: string not found for pid %d\n", pid); | ||
113 | } | ||
94 | 114 | ||
95 | return tgid; | 115 | if (ppids) { |
116 | ppids += 5; /* strlen("PPid:") */ | ||
117 | *ppid = atoi(ppids); | ||
118 | } else { | ||
119 | pr_debug("PPid: string not found for pid %d\n", pid); | ||
120 | } | ||
121 | |||
122 | return 0; | ||
96 | } | 123 | } |
97 | 124 | ||
98 | static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | 125 | static int perf_event__prepare_comm(union perf_event *event, pid_t pid, |
99 | struct machine *machine) | 126 | struct machine *machine, |
127 | pid_t *tgid, pid_t *ppid) | ||
100 | { | 128 | { |
101 | size_t size; | 129 | size_t size; |
102 | pid_t tgid; | 130 | |
131 | *ppid = -1; | ||
103 | 132 | ||
104 | memset(&event->comm, 0, sizeof(event->comm)); | 133 | memset(&event->comm, 0, sizeof(event->comm)); |
105 | 134 | ||
106 | if (machine__is_host(machine)) | 135 | if (machine__is_host(machine)) { |
107 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | 136 | if (perf_event__get_comm_ids(pid, event->comm.comm, |
108 | sizeof(event->comm.comm)); | 137 | sizeof(event->comm.comm), |
109 | else | 138 | tgid, ppid) != 0) { |
110 | tgid = machine->pid; | 139 | return -1; |
140 | } | ||
141 | } else { | ||
142 | *tgid = machine->pid; | ||
143 | } | ||
111 | 144 | ||
112 | if (tgid < 0) | 145 | if (*tgid < 0) |
113 | goto out; | 146 | return -1; |
114 | 147 | ||
115 | event->comm.pid = tgid; | 148 | event->comm.pid = *tgid; |
116 | event->comm.header.type = PERF_RECORD_COMM; | 149 | event->comm.header.type = PERF_RECORD_COMM; |
117 | 150 | ||
118 | size = strlen(event->comm.comm) + 1; | 151 | size = strlen(event->comm.comm) + 1; |
@@ -122,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | |||
122 | (sizeof(event->comm.comm) - size) + | 155 | (sizeof(event->comm.comm) - size) + |
123 | machine->id_hdr_size); | 156 | machine->id_hdr_size); |
124 | event->comm.tid = pid; | 157 | event->comm.tid = pid; |
125 | out: | 158 | |
126 | return tgid; | 159 | return 0; |
127 | } | 160 | } |
128 | 161 | ||
129 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | 162 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, |
@@ -131,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
131 | perf_event__handler_t process, | 164 | perf_event__handler_t process, |
132 | struct machine *machine) | 165 | struct machine *machine) |
133 | { | 166 | { |
134 | pid_t tgid = perf_event__prepare_comm(event, pid, machine); | 167 | pid_t tgid, ppid; |
135 | 168 | ||
136 | if (tgid == -1) | 169 | if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0) |
137 | goto out; | 170 | return -1; |
138 | 171 | ||
139 | if (process(tool, event, &synth_sample, machine) != 0) | 172 | if (process(tool, event, &synth_sample, machine) != 0) |
140 | return -1; | 173 | return -1; |
141 | 174 | ||
142 | out: | ||
143 | return tgid; | 175 | return tgid; |
144 | } | 176 | } |
145 | 177 | ||
146 | static int perf_event__synthesize_fork(struct perf_tool *tool, | 178 | static int perf_event__synthesize_fork(struct perf_tool *tool, |
147 | union perf_event *event, pid_t pid, | 179 | union perf_event *event, |
148 | pid_t tgid, perf_event__handler_t process, | 180 | pid_t pid, pid_t tgid, pid_t ppid, |
181 | perf_event__handler_t process, | ||
149 | struct machine *machine) | 182 | struct machine *machine) |
150 | { | 183 | { |
151 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); | 184 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); |
152 | 185 | ||
153 | event->fork.ppid = tgid; | 186 | event->fork.ppid = ppid; |
154 | event->fork.ptid = tgid; | 187 | event->fork.ptid = ppid; |
155 | event->fork.pid = tgid; | 188 | event->fork.pid = tgid; |
156 | event->fork.tid = pid; | 189 | event->fork.tid = pid; |
157 | event->fork.header.type = PERF_RECORD_FORK; | 190 | event->fork.header.type = PERF_RECORD_FORK; |
@@ -343,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
343 | char filename[PATH_MAX]; | 376 | char filename[PATH_MAX]; |
344 | DIR *tasks; | 377 | DIR *tasks; |
345 | struct dirent dirent, *next; | 378 | struct dirent dirent, *next; |
346 | pid_t tgid; | 379 | pid_t tgid, ppid; |
347 | 380 | ||
348 | /* special case: only send one comm event using passed in pid */ | 381 | /* special case: only send one comm event using passed in pid */ |
349 | if (!full) { | 382 | if (!full) { |
@@ -378,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
378 | if (*end) | 411 | if (*end) |
379 | continue; | 412 | continue; |
380 | 413 | ||
381 | tgid = perf_event__prepare_comm(comm_event, _pid, machine); | 414 | if (perf_event__prepare_comm(comm_event, _pid, machine, |
382 | if (tgid == -1) | 415 | &tgid, &ppid) != 0) |
383 | return -1; | 416 | return -1; |
384 | 417 | ||
385 | if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, | 418 | if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, |
386 | process, machine) < 0) | 419 | ppid, process, machine) < 0) |
387 | return -1; | 420 | return -1; |
388 | /* | 421 | /* |
389 | * Send the prepared comm event | 422 | * Send the prepared comm event |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c4ffe2bd0738..09b9e8d3fcf7 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -242,7 +242,6 @@ struct events_stats { | |||
242 | u32 nr_invalid_chains; | 242 | u32 nr_invalid_chains; |
243 | u32 nr_unknown_id; | 243 | u32 nr_unknown_id; |
244 | u32 nr_unprocessable_samples; | 244 | u32 nr_unprocessable_samples; |
245 | u32 nr_unordered_events; | ||
246 | }; | 245 | }; |
247 | 246 | ||
248 | struct attr_event { | 247 | struct attr_event { |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e3353307330c..e45c8f33a8fd 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1408,29 +1408,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, | |||
1408 | static int add_callchain_ip(struct thread *thread, | 1408 | static int add_callchain_ip(struct thread *thread, |
1409 | struct symbol **parent, | 1409 | struct symbol **parent, |
1410 | struct addr_location *root_al, | 1410 | struct addr_location *root_al, |
1411 | bool branch_history, | 1411 | u8 *cpumode, |
1412 | u64 ip) | 1412 | u64 ip) |
1413 | { | 1413 | { |
1414 | struct addr_location al; | 1414 | struct addr_location al; |
1415 | 1415 | ||
1416 | al.filtered = 0; | 1416 | al.filtered = 0; |
1417 | al.sym = NULL; | 1417 | al.sym = NULL; |
1418 | if (branch_history) | 1418 | if (!cpumode) { |
1419 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, | 1419 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, |
1420 | ip, &al); | 1420 | ip, &al); |
1421 | else { | 1421 | } else { |
1422 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1423 | |||
1424 | if (ip >= PERF_CONTEXT_MAX) { | 1422 | if (ip >= PERF_CONTEXT_MAX) { |
1425 | switch (ip) { | 1423 | switch (ip) { |
1426 | case PERF_CONTEXT_HV: | 1424 | case PERF_CONTEXT_HV: |
1427 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | 1425 | *cpumode = PERF_RECORD_MISC_HYPERVISOR; |
1428 | break; | 1426 | break; |
1429 | case PERF_CONTEXT_KERNEL: | 1427 | case PERF_CONTEXT_KERNEL: |
1430 | cpumode = PERF_RECORD_MISC_KERNEL; | 1428 | *cpumode = PERF_RECORD_MISC_KERNEL; |
1431 | break; | 1429 | break; |
1432 | case PERF_CONTEXT_USER: | 1430 | case PERF_CONTEXT_USER: |
1433 | cpumode = PERF_RECORD_MISC_USER; | 1431 | *cpumode = PERF_RECORD_MISC_USER; |
1434 | break; | 1432 | break; |
1435 | default: | 1433 | default: |
1436 | pr_debug("invalid callchain context: " | 1434 | pr_debug("invalid callchain context: " |
@@ -1444,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread, | |||
1444 | } | 1442 | } |
1445 | return 0; | 1443 | return 0; |
1446 | } | 1444 | } |
1447 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | 1445 | thread__find_addr_location(thread, *cpumode, MAP__FUNCTION, |
1448 | ip, &al); | 1446 | ip, &al); |
1449 | } | 1447 | } |
1450 | 1448 | ||
1451 | if (al.sym != NULL) { | 1449 | if (al.sym != NULL) { |
@@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, | |||
1538 | { | 1536 | { |
1539 | struct ip_callchain *chain = sample->callchain; | 1537 | struct ip_callchain *chain = sample->callchain; |
1540 | int chain_nr = min(max_stack, (int)chain->nr); | 1538 | int chain_nr = min(max_stack, (int)chain->nr); |
1539 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1541 | int i, j, err; | 1540 | int i, j, err; |
1542 | u64 ip; | 1541 | u64 ip; |
1543 | 1542 | ||
@@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, | |||
1584 | ip = lbr_stack->entries[0].to; | 1583 | ip = lbr_stack->entries[0].to; |
1585 | } | 1584 | } |
1586 | 1585 | ||
1587 | err = add_callchain_ip(thread, parent, root_al, false, ip); | 1586 | err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); |
1588 | if (err) | 1587 | if (err) |
1589 | return (err < 0) ? err : 0; | 1588 | return (err < 0) ? err : 0; |
1590 | } | 1589 | } |
@@ -1604,6 +1603,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1604 | struct branch_stack *branch = sample->branch_stack; | 1603 | struct branch_stack *branch = sample->branch_stack; |
1605 | struct ip_callchain *chain = sample->callchain; | 1604 | struct ip_callchain *chain = sample->callchain; |
1606 | int chain_nr = min(max_stack, (int)chain->nr); | 1605 | int chain_nr = min(max_stack, (int)chain->nr); |
1606 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
1607 | int i, j, err; | 1607 | int i, j, err; |
1608 | int skip_idx = -1; | 1608 | int skip_idx = -1; |
1609 | int first_call = 0; | 1609 | int first_call = 0; |
@@ -1669,10 +1669,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1669 | 1669 | ||
1670 | for (i = 0; i < nr; i++) { | 1670 | for (i = 0; i < nr; i++) { |
1671 | err = add_callchain_ip(thread, parent, root_al, | 1671 | err = add_callchain_ip(thread, parent, root_al, |
1672 | true, be[i].to); | 1672 | NULL, be[i].to); |
1673 | if (!err) | 1673 | if (!err) |
1674 | err = add_callchain_ip(thread, parent, root_al, | 1674 | err = add_callchain_ip(thread, parent, root_al, |
1675 | true, be[i].from); | 1675 | NULL, be[i].from); |
1676 | if (err == -EINVAL) | 1676 | if (err == -EINVAL) |
1677 | break; | 1677 | break; |
1678 | if (err) | 1678 | if (err) |
@@ -1701,7 +1701,7 @@ check_calls: | |||
1701 | #endif | 1701 | #endif |
1702 | ip = chain->ips[j]; | 1702 | ip = chain->ips[j]; |
1703 | 1703 | ||
1704 | err = add_callchain_ip(thread, parent, root_al, false, ip); | 1704 | err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); |
1705 | 1705 | ||
1706 | if (err) | 1706 | if (err) |
1707 | return (err < 0) ? err : 0; | 1707 | return (err < 0) ? err : 0; |
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 6002fa3fcf77..52be201b9b25 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c | |||
@@ -2,7 +2,6 @@ | |||
2 | #include <linux/compiler.h> | 2 | #include <linux/compiler.h> |
3 | #include <linux/string.h> | 3 | #include <linux/string.h> |
4 | #include "ordered-events.h" | 4 | #include "ordered-events.h" |
5 | #include "evlist.h" | ||
6 | #include "session.h" | 5 | #include "session.h" |
7 | #include "asm/bug.h" | 6 | #include "asm/bug.h" |
8 | #include "debug.h" | 7 | #include "debug.h" |
@@ -167,7 +166,7 @@ int ordered_events__queue(struct ordered_events *oe, union perf_event *event, | |||
167 | pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", | 166 | pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", |
168 | oe->last_flush_type); | 167 | oe->last_flush_type); |
169 | 168 | ||
170 | oe->evlist->stats.nr_unordered_events++; | 169 | oe->nr_unordered_events++; |
171 | } | 170 | } |
172 | 171 | ||
173 | oevent = ordered_events__new_event(oe, timestamp, event); | 172 | oevent = ordered_events__new_event(oe, timestamp, event); |
@@ -187,7 +186,6 @@ static int __ordered_events__flush(struct ordered_events *oe) | |||
187 | { | 186 | { |
188 | struct list_head *head = &oe->events; | 187 | struct list_head *head = &oe->events; |
189 | struct ordered_event *tmp, *iter; | 188 | struct ordered_event *tmp, *iter; |
190 | struct perf_sample sample; | ||
191 | u64 limit = oe->next_flush; | 189 | u64 limit = oe->next_flush; |
192 | u64 last_ts = oe->last ? oe->last->timestamp : 0ULL; | 190 | u64 last_ts = oe->last ? oe->last->timestamp : 0ULL; |
193 | bool show_progress = limit == ULLONG_MAX; | 191 | bool show_progress = limit == ULLONG_MAX; |
@@ -206,15 +204,9 @@ static int __ordered_events__flush(struct ordered_events *oe) | |||
206 | 204 | ||
207 | if (iter->timestamp > limit) | 205 | if (iter->timestamp > limit) |
208 | break; | 206 | break; |
209 | 207 | ret = oe->deliver(oe, iter); | |
210 | ret = perf_evlist__parse_sample(oe->evlist, iter->event, &sample); | ||
211 | if (ret) | 208 | if (ret) |
212 | pr_err("Can't parse sample, err = %d\n", ret); | 209 | return ret; |
213 | else { | ||
214 | ret = oe->deliver(oe, iter, &sample); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | } | ||
218 | 210 | ||
219 | ordered_events__delete(oe, iter); | 211 | ordered_events__delete(oe, iter); |
220 | oe->last_flush = iter->timestamp; | 212 | oe->last_flush = iter->timestamp; |
@@ -292,18 +284,13 @@ int ordered_events__flush(struct ordered_events *oe, enum oe_flush how) | |||
292 | return err; | 284 | return err; |
293 | } | 285 | } |
294 | 286 | ||
295 | void ordered_events__init(struct ordered_events *oe, struct machines *machines, | 287 | void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver) |
296 | struct perf_evlist *evlist, struct perf_tool *tool, | ||
297 | ordered_events__deliver_t deliver) | ||
298 | { | 288 | { |
299 | INIT_LIST_HEAD(&oe->events); | 289 | INIT_LIST_HEAD(&oe->events); |
300 | INIT_LIST_HEAD(&oe->cache); | 290 | INIT_LIST_HEAD(&oe->cache); |
301 | INIT_LIST_HEAD(&oe->to_free); | 291 | INIT_LIST_HEAD(&oe->to_free); |
302 | oe->max_alloc_size = (u64) -1; | 292 | oe->max_alloc_size = (u64) -1; |
303 | oe->cur_alloc_size = 0; | 293 | oe->cur_alloc_size = 0; |
304 | oe->evlist = evlist; | ||
305 | oe->machines = machines; | ||
306 | oe->tool = tool; | ||
307 | oe->deliver = deliver; | 294 | oe->deliver = deliver; |
308 | } | 295 | } |
309 | 296 | ||
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h index 173e13f28c08..f403991e3bfd 100644 --- a/tools/perf/util/ordered-events.h +++ b/tools/perf/util/ordered-events.h | |||
@@ -3,10 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | struct perf_tool; | ||
7 | struct perf_evlist; | ||
8 | struct perf_sample; | 6 | struct perf_sample; |
9 | struct machines; | ||
10 | 7 | ||
11 | struct ordered_event { | 8 | struct ordered_event { |
12 | u64 timestamp; | 9 | u64 timestamp; |
@@ -25,8 +22,7 @@ enum oe_flush { | |||
25 | struct ordered_events; | 22 | struct ordered_events; |
26 | 23 | ||
27 | typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, | 24 | typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, |
28 | struct ordered_event *event, | 25 | struct ordered_event *event); |
29 | struct perf_sample *sample); | ||
30 | 26 | ||
31 | struct ordered_events { | 27 | struct ordered_events { |
32 | u64 last_flush; | 28 | u64 last_flush; |
@@ -39,13 +35,11 @@ struct ordered_events { | |||
39 | struct list_head to_free; | 35 | struct list_head to_free; |
40 | struct ordered_event *buffer; | 36 | struct ordered_event *buffer; |
41 | struct ordered_event *last; | 37 | struct ordered_event *last; |
42 | struct machines *machines; | ||
43 | struct perf_evlist *evlist; | ||
44 | struct perf_tool *tool; | ||
45 | ordered_events__deliver_t deliver; | 38 | ordered_events__deliver_t deliver; |
46 | int buffer_idx; | 39 | int buffer_idx; |
47 | unsigned int nr_events; | 40 | unsigned int nr_events; |
48 | enum oe_flush last_flush_type; | 41 | enum oe_flush last_flush_type; |
42 | u32 nr_unordered_events; | ||
49 | bool copy_on_queue; | 43 | bool copy_on_queue; |
50 | }; | 44 | }; |
51 | 45 | ||
@@ -53,9 +47,7 @@ int ordered_events__queue(struct ordered_events *oe, union perf_event *event, | |||
53 | struct perf_sample *sample, u64 file_offset); | 47 | struct perf_sample *sample, u64 file_offset); |
54 | void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); | 48 | void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); |
55 | int ordered_events__flush(struct ordered_events *oe, enum oe_flush how); | 49 | int ordered_events__flush(struct ordered_events *oe, enum oe_flush how); |
56 | void ordered_events__init(struct ordered_events *oe, struct machines *machines, | 50 | void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver); |
57 | struct perf_evlist *evlsit, struct perf_tool *tool, | ||
58 | ordered_events__deliver_t deliver); | ||
59 | void ordered_events__free(struct ordered_events *oe); | 51 | void ordered_events__free(struct ordered_events *oe); |
60 | 52 | ||
61 | static inline | 53 | static inline |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index adf0740c563b..dfacf1d50162 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -93,11 +93,20 @@ static void perf_session__set_comm_exec(struct perf_session *session) | |||
93 | } | 93 | } |
94 | 94 | ||
95 | static int ordered_events__deliver_event(struct ordered_events *oe, | 95 | static int ordered_events__deliver_event(struct ordered_events *oe, |
96 | struct ordered_event *event, | 96 | struct ordered_event *event) |
97 | struct perf_sample *sample) | ||
98 | { | 97 | { |
99 | return machines__deliver_event(oe->machines, oe->evlist, event->event, | 98 | struct perf_sample sample; |
100 | sample, oe->tool, event->file_offset); | 99 | struct perf_session *session = container_of(oe, struct perf_session, |
100 | ordered_events); | ||
101 | int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample); | ||
102 | |||
103 | if (ret) { | ||
104 | pr_err("Can't parse sample, err = %d\n", ret); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | return machines__deliver_event(&session->machines, session->evlist, event->event, | ||
109 | &sample, session->tool, event->file_offset); | ||
101 | } | 110 | } |
102 | 111 | ||
103 | struct perf_session *perf_session__new(struct perf_data_file *file, | 112 | struct perf_session *perf_session__new(struct perf_data_file *file, |
@@ -109,7 +118,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
109 | goto out; | 118 | goto out; |
110 | 119 | ||
111 | session->repipe = repipe; | 120 | session->repipe = repipe; |
121 | session->tool = tool; | ||
112 | machines__init(&session->machines); | 122 | machines__init(&session->machines); |
123 | ordered_events__init(&session->ordered_events, ordered_events__deliver_event); | ||
113 | 124 | ||
114 | if (file) { | 125 | if (file) { |
115 | if (perf_data_file__open(file)) | 126 | if (perf_data_file__open(file)) |
@@ -139,9 +150,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
139 | tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { | 150 | tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { |
140 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); | 151 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); |
141 | tool->ordered_events = false; | 152 | tool->ordered_events = false; |
142 | } else { | ||
143 | ordered_events__init(&session->ordered_events, &session->machines, | ||
144 | session->evlist, tool, ordered_events__deliver_event); | ||
145 | } | 153 | } |
146 | 154 | ||
147 | return session; | 155 | return session; |
@@ -941,7 +949,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
941 | u64 file_offset) | 949 | u64 file_offset) |
942 | { | 950 | { |
943 | struct ordered_events *oe = &session->ordered_events; | 951 | struct ordered_events *oe = &session->ordered_events; |
944 | struct perf_tool *tool = oe->tool; | 952 | struct perf_tool *tool = session->tool; |
945 | int fd = perf_data_file__fd(session->file); | 953 | int fd = perf_data_file__fd(session->file); |
946 | int err; | 954 | int err; |
947 | 955 | ||
@@ -982,7 +990,7 @@ int perf_session__deliver_synth_event(struct perf_session *session, | |||
982 | struct perf_sample *sample) | 990 | struct perf_sample *sample) |
983 | { | 991 | { |
984 | struct perf_evlist *evlist = session->evlist; | 992 | struct perf_evlist *evlist = session->evlist; |
985 | struct perf_tool *tool = session->ordered_events.tool; | 993 | struct perf_tool *tool = session->tool; |
986 | 994 | ||
987 | events_stats__inc(&evlist->stats, event->header.type); | 995 | events_stats__inc(&evlist->stats, event->header.type); |
988 | 996 | ||
@@ -1060,7 +1068,7 @@ static s64 perf_session__process_event(struct perf_session *session, | |||
1060 | union perf_event *event, u64 file_offset) | 1068 | union perf_event *event, u64 file_offset) |
1061 | { | 1069 | { |
1062 | struct perf_evlist *evlist = session->evlist; | 1070 | struct perf_evlist *evlist = session->evlist; |
1063 | struct perf_tool *tool = session->ordered_events.tool; | 1071 | struct perf_tool *tool = session->tool; |
1064 | struct perf_sample sample; | 1072 | struct perf_sample sample; |
1065 | int ret; | 1073 | int ret; |
1066 | 1074 | ||
@@ -1117,10 +1125,12 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se | |||
1117 | return thread; | 1125 | return thread; |
1118 | } | 1126 | } |
1119 | 1127 | ||
1120 | static void perf_tool__warn_about_errors(const struct perf_tool *tool, | 1128 | static void perf_session__warn_about_errors(const struct perf_session *session) |
1121 | const struct events_stats *stats) | ||
1122 | { | 1129 | { |
1123 | if (tool->lost == perf_event__process_lost && | 1130 | const struct events_stats *stats = &session->evlist->stats; |
1131 | const struct ordered_events *oe = &session->ordered_events; | ||
1132 | |||
1133 | if (session->tool->lost == perf_event__process_lost && | ||
1124 | stats->nr_events[PERF_RECORD_LOST] != 0) { | 1134 | stats->nr_events[PERF_RECORD_LOST] != 0) { |
1125 | ui__warning("Processed %d events and lost %d chunks!\n\n" | 1135 | ui__warning("Processed %d events and lost %d chunks!\n\n" |
1126 | "Check IO/CPU overload!\n\n", | 1136 | "Check IO/CPU overload!\n\n", |
@@ -1156,8 +1166,8 @@ static void perf_tool__warn_about_errors(const struct perf_tool *tool, | |||
1156 | stats->nr_unprocessable_samples); | 1166 | stats->nr_unprocessable_samples); |
1157 | } | 1167 | } |
1158 | 1168 | ||
1159 | if (stats->nr_unordered_events != 0) | 1169 | if (oe->nr_unordered_events != 0) |
1160 | ui__warning("%u out of order events recorded.\n", stats->nr_unordered_events); | 1170 | ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events); |
1161 | } | 1171 | } |
1162 | 1172 | ||
1163 | volatile int session_done; | 1173 | volatile int session_done; |
@@ -1165,7 +1175,7 @@ volatile int session_done; | |||
1165 | static int __perf_session__process_pipe_events(struct perf_session *session) | 1175 | static int __perf_session__process_pipe_events(struct perf_session *session) |
1166 | { | 1176 | { |
1167 | struct ordered_events *oe = &session->ordered_events; | 1177 | struct ordered_events *oe = &session->ordered_events; |
1168 | struct perf_tool *tool = oe->tool; | 1178 | struct perf_tool *tool = session->tool; |
1169 | int fd = perf_data_file__fd(session->file); | 1179 | int fd = perf_data_file__fd(session->file); |
1170 | union perf_event *event; | 1180 | union perf_event *event; |
1171 | uint32_t size, cur_size = 0; | 1181 | uint32_t size, cur_size = 0; |
@@ -1248,7 +1258,7 @@ done: | |||
1248 | err = ordered_events__flush(oe, OE_FLUSH__FINAL); | 1258 | err = ordered_events__flush(oe, OE_FLUSH__FINAL); |
1249 | out_err: | 1259 | out_err: |
1250 | free(buf); | 1260 | free(buf); |
1251 | perf_tool__warn_about_errors(tool, &session->evlist->stats); | 1261 | perf_session__warn_about_errors(session); |
1252 | ordered_events__free(&session->ordered_events); | 1262 | ordered_events__free(&session->ordered_events); |
1253 | return err; | 1263 | return err; |
1254 | } | 1264 | } |
@@ -1298,7 +1308,7 @@ static int __perf_session__process_events(struct perf_session *session, | |||
1298 | u64 file_size) | 1308 | u64 file_size) |
1299 | { | 1309 | { |
1300 | struct ordered_events *oe = &session->ordered_events; | 1310 | struct ordered_events *oe = &session->ordered_events; |
1301 | struct perf_tool *tool = oe->tool; | 1311 | struct perf_tool *tool = session->tool; |
1302 | int fd = perf_data_file__fd(session->file); | 1312 | int fd = perf_data_file__fd(session->file); |
1303 | u64 head, page_offset, file_offset, file_pos, size; | 1313 | u64 head, page_offset, file_offset, file_pos, size; |
1304 | int err, mmap_prot, mmap_flags, map_idx = 0; | 1314 | int err, mmap_prot, mmap_flags, map_idx = 0; |
@@ -1394,7 +1404,7 @@ out: | |||
1394 | err = ordered_events__flush(oe, OE_FLUSH__FINAL); | 1404 | err = ordered_events__flush(oe, OE_FLUSH__FINAL); |
1395 | out_err: | 1405 | out_err: |
1396 | ui_progress__finish(); | 1406 | ui_progress__finish(); |
1397 | perf_tool__warn_about_errors(tool, &session->evlist->stats); | 1407 | perf_session__warn_about_errors(session); |
1398 | ordered_events__free(&session->ordered_events); | 1408 | ordered_events__free(&session->ordered_events); |
1399 | session->one_mmap = false; | 1409 | session->one_mmap = false; |
1400 | return err; | 1410 | return err; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 1310998f8318..d5fa7b7916ef 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -26,6 +26,7 @@ struct perf_session { | |||
26 | u64 one_mmap_offset; | 26 | u64 one_mmap_offset; |
27 | struct ordered_events ordered_events; | 27 | struct ordered_events ordered_events; |
28 | struct perf_data_file *file; | 28 | struct perf_data_file *file; |
29 | struct perf_tool *tool; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | #define PRINT_IP_OPT_IP (1<<0) | 32 | #define PRINT_IP_OPT_IP (1<<0) |