aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-04-01 03:55:17 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-01 03:55:17 -0400
commitaaa9fa387541a30f6f4138bea6e082319de5e3fe (patch)
tree43905494fe3c7724b8fe4326a4e820e897e7a7e9
parentccd41c86ad4d464d0ed4e48d80759ff85c2115b0 (diff)
parent9870d7809575515e26194f4b3df1750872a6ee60 (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.perf2
-rw-r--r--tools/perf/config/Makefile5
-rw-r--r--tools/perf/util/event.c147
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/machine.c28
-rw-r--r--tools/perf/util/ordered-events.c21
-rw-r--r--tools/perf/util/ordered-events.h14
-rw-r--r--tools/perf/util/session.c48
-rw-r--r--tools/perf/util/session.h1
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
96endif 96endif
97 97
98ifndef NO_LIBBABELTRACE 98ifdef 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
599endif 599endif
600 600
601ifndef NO_LIBBABELTRACE 601ifdef 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
612endif 611endif
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
52static 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 */
56static 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
98static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, 125static 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;
125out: 158
126 return tgid; 159 return 0;
127} 160}
128 161
129static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 162static 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
142out:
143 return tgid; 175 return tgid;
144} 176}
145 177
146static int perf_event__synthesize_fork(struct perf_tool *tool, 178static 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
248struct attr_event { 247struct 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,
1408static int add_callchain_ip(struct thread *thread, 1408static 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
295void ordered_events__init(struct ordered_events *oe, struct machines *machines, 287void 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
6struct perf_tool;
7struct perf_evlist;
8struct perf_sample; 6struct perf_sample;
9struct machines;
10 7
11struct ordered_event { 8struct ordered_event {
12 u64 timestamp; 9 u64 timestamp;
@@ -25,8 +22,7 @@ enum oe_flush {
25struct ordered_events; 22struct ordered_events;
26 23
27typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, 24typedef 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
31struct ordered_events { 27struct 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);
54void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); 48void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
55int ordered_events__flush(struct ordered_events *oe, enum oe_flush how); 49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
56void ordered_events__init(struct ordered_events *oe, struct machines *machines, 50void 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);
59void ordered_events__free(struct ordered_events *oe); 51void ordered_events__free(struct ordered_events *oe);
60 52
61static inline 53static 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
95static int ordered_events__deliver_event(struct ordered_events *oe, 95static 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
103struct perf_session *perf_session__new(struct perf_data_file *file, 112struct 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
1120static void perf_tool__warn_about_errors(const struct perf_tool *tool, 1128static 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
1163volatile int session_done; 1173volatile int session_done;
@@ -1165,7 +1175,7 @@ volatile int session_done;
1165static int __perf_session__process_pipe_events(struct perf_session *session) 1175static 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);
1249out_err: 1259out_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);
1395out_err: 1405out_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)