Эх сурвалжийг харах

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>
Ingo Molnar 10 жил өмнө
parent
commit
aaa9fa3875

+ 1 - 1
tools/perf/Makefile.perf

@@ -69,7 +69,7 @@ include config/utilities.mak
 #
 #
 # Define NO_ZLIB if you do not want to support compressed kernel modules
 # Define NO_ZLIB if you do not want to support compressed kernel modules
 #
 #
-# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
+# Define LIBBABELTRACE if you DO want libbabeltrace support
 # for CTF data format.
 # for CTF data format.
 #
 #
 # Define NO_LZMA if you do not want to support compressed (xz) kernel modules
 # Define NO_LZMA if you do not want to support compressed (xz) kernel modules

+ 2 - 3
tools/perf/config/Makefile

@@ -95,7 +95,7 @@ ifndef NO_LIBELF
   FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
   FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
 endif
 endif
 
 
-ifndef NO_LIBBABELTRACE
+ifdef LIBBABELTRACE
   # for linking with debug library, run like:
   # for linking with debug library, run like:
   # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
   # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
   ifdef LIBBABELTRACE_DIR
   ifdef LIBBABELTRACE_DIR
@@ -598,7 +598,7 @@ else
   NO_PERF_READ_VDSOX32 := 1
   NO_PERF_READ_VDSOX32 := 1
 endif
 endif
 
 
-ifndef NO_LIBBABELTRACE
+ifdef LIBBABELTRACE
   $(call feature_check,libbabeltrace)
   $(call feature_check,libbabeltrace)
   ifeq ($(feature-libbabeltrace), 1)
   ifeq ($(feature-libbabeltrace), 1)
     CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
     CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
@@ -607,7 +607,6 @@ ifndef NO_LIBBABELTRACE
     $(call detected,CONFIG_LIBBABELTRACE)
     $(call detected,CONFIG_LIBBABELTRACE)
   else
   else
     msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
     msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
-    NO_LIBBABELTRACE := 1
   endif
   endif
 endif
 endif
 
 

+ 90 - 57
tools/perf/util/event.c

@@ -49,70 +49,103 @@ static struct perf_sample synth_sample = {
 	.period	   = 1,
 	.period	   = 1,
 };
 };
 
 
-static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
+/*
+ * Assumes that the first 4095 bytes of /proc/pid/stat contains
+ * the comm, tgid and ppid.
+ */
+static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
+				    pid_t *tgid, pid_t *ppid)
 {
 {
 	char filename[PATH_MAX];
 	char filename[PATH_MAX];
-	char bf[BUFSIZ];
-	FILE *fp;
-	size_t size = 0;
-	pid_t tgid = -1;
+	char bf[4096];
+	int fd;
+	size_t size = 0, n;
+	char *nl, *name, *tgids, *ppids;
+
+	*tgid = -1;
+	*ppid = -1;
 
 
 	snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
 	snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
 
 
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
 		pr_debug("couldn't open %s\n", filename);
 		pr_debug("couldn't open %s\n", filename);
-		return 0;
+		return -1;
 	}
 	}
 
 
-	while (!comm[0] || (tgid < 0)) {
-		if (fgets(bf, sizeof(bf), fp) == NULL) {
-			pr_warning("couldn't get COMM and pgid, malformed %s\n",
-				   filename);
-			break;
-		}
+	n = read(fd, bf, sizeof(bf) - 1);
+	close(fd);
+	if (n <= 0) {
+		pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
+			   pid);
+		return -1;
+	}
+	bf[n] = '\0';
 
 
-		if (memcmp(bf, "Name:", 5) == 0) {
-			char *name = bf + 5;
-			while (*name && isspace(*name))
-				++name;
-			size = strlen(name) - 1;
-			if (size >= len)
-				size = len - 1;
-			memcpy(comm, name, size);
-			comm[size] = '\0';
-
-		} else if (memcmp(bf, "Tgid:", 5) == 0) {
-			char *tgids = bf + 5;
-			while (*tgids && isspace(*tgids))
-				++tgids;
-			tgid = atoi(tgids);
-		}
+	name = strstr(bf, "Name:");
+	tgids = strstr(bf, "Tgid:");
+	ppids = strstr(bf, "PPid:");
+
+	if (name) {
+		name += 5;  /* strlen("Name:") */
+
+		while (*name && isspace(*name))
+			++name;
+
+		nl = strchr(name, '\n');
+		if (nl)
+			*nl = '\0';
+
+		size = strlen(name);
+		if (size >= len)
+			size = len - 1;
+		memcpy(comm, name, size);
+		comm[size] = '\0';
+	} else {
+		pr_debug("Name: string not found for pid %d\n", pid);
 	}
 	}
 
 
-	fclose(fp);
+	if (tgids) {
+		tgids += 5;  /* strlen("Tgid:") */
+		*tgid = atoi(tgids);
+	} else {
+		pr_debug("Tgid: string not found for pid %d\n", pid);
+	}
 
 
-	return tgid;
+	if (ppids) {
+		ppids += 5;  /* strlen("PPid:") */
+		*ppid = atoi(ppids);
+	} else {
+		pr_debug("PPid: string not found for pid %d\n", pid);
+	}
+
+	return 0;
 }
 }
 
 
-static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
-					 struct machine *machine)
+static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
+				    struct machine *machine,
+				    pid_t *tgid, pid_t *ppid)
 {
 {
 	size_t size;
 	size_t size;
-	pid_t tgid;
+
+	*ppid = -1;
 
 
 	memset(&event->comm, 0, sizeof(event->comm));
 	memset(&event->comm, 0, sizeof(event->comm));
 
 
-	if (machine__is_host(machine))
-		tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
-						 sizeof(event->comm.comm));
-	else
-		tgid = machine->pid;
+	if (machine__is_host(machine)) {
+		if (perf_event__get_comm_ids(pid, event->comm.comm,
+					     sizeof(event->comm.comm),
+					     tgid, ppid) != 0) {
+			return -1;
+		}
+	} else {
+		*tgid = machine->pid;
+	}
 
 
-	if (tgid < 0)
-		goto out;
+	if (*tgid < 0)
+		return -1;
 
 
-	event->comm.pid = tgid;
+	event->comm.pid = *tgid;
 	event->comm.header.type = PERF_RECORD_COMM;
 	event->comm.header.type = PERF_RECORD_COMM;
 
 
 	size = strlen(event->comm.comm) + 1;
 	size = strlen(event->comm.comm) + 1;
@@ -122,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
 				(sizeof(event->comm.comm) - size) +
 				(sizeof(event->comm.comm) - size) +
 				machine->id_hdr_size);
 				machine->id_hdr_size);
 	event->comm.tid = pid;
 	event->comm.tid = pid;
-out:
-	return tgid;
+
+	return 0;
 }
 }
 
 
 static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
 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,
 					 perf_event__handler_t process,
 					 perf_event__handler_t process,
 					 struct machine *machine)
 					 struct machine *machine)
 {
 {
-	pid_t tgid = perf_event__prepare_comm(event, pid, machine);
+	pid_t tgid, ppid;
 
 
-	if (tgid == -1)
-		goto out;
+	if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
+		return -1;
 
 
 	if (process(tool, event, &synth_sample, machine) != 0)
 	if (process(tool, event, &synth_sample, machine) != 0)
 		return -1;
 		return -1;
 
 
-out:
 	return tgid;
 	return tgid;
 }
 }
 
 
 static int perf_event__synthesize_fork(struct perf_tool *tool,
 static int perf_event__synthesize_fork(struct perf_tool *tool,
-				       union perf_event *event, pid_t pid,
-				       pid_t tgid, perf_event__handler_t process,
+				       union perf_event *event,
+				       pid_t pid, pid_t tgid, pid_t ppid,
+				       perf_event__handler_t process,
 				       struct machine *machine)
 				       struct machine *machine)
 {
 {
 	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 
 
-	event->fork.ppid = tgid;
-	event->fork.ptid = tgid;
+	event->fork.ppid = ppid;
+	event->fork.ptid = ppid;
 	event->fork.pid  = tgid;
 	event->fork.pid  = tgid;
 	event->fork.tid  = pid;
 	event->fork.tid  = pid;
 	event->fork.header.type = PERF_RECORD_FORK;
 	event->fork.header.type = PERF_RECORD_FORK;
@@ -343,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 	char filename[PATH_MAX];
 	char filename[PATH_MAX];
 	DIR *tasks;
 	DIR *tasks;
 	struct dirent dirent, *next;
 	struct dirent dirent, *next;
-	pid_t tgid;
+	pid_t tgid, ppid;
 
 
 	/* special case: only send one comm event using passed in pid */
 	/* special case: only send one comm event using passed in pid */
 	if (!full) {
 	if (!full) {
@@ -378,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 		if (*end)
 		if (*end)
 			continue;
 			continue;
 
 
-		tgid = perf_event__prepare_comm(comm_event, _pid, machine);
-		if (tgid == -1)
+		if (perf_event__prepare_comm(comm_event, _pid, machine,
+					     &tgid, &ppid) != 0)
 			return -1;
 			return -1;
 
 
 		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
 		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
-						process, machine) < 0)
+						ppid, process, machine) < 0)
 			return -1;
 			return -1;
 		/*
 		/*
 		 * Send the prepared comm event
 		 * Send the prepared comm event

+ 0 - 1
tools/perf/util/event.h

@@ -242,7 +242,6 @@ struct events_stats {
 	u32 nr_invalid_chains;
 	u32 nr_invalid_chains;
 	u32 nr_unknown_id;
 	u32 nr_unknown_id;
 	u32 nr_unprocessable_samples;
 	u32 nr_unprocessable_samples;
-	u32 nr_unordered_events;
 };
 };
 
 
 struct attr_event {
 struct attr_event {

+ 14 - 14
tools/perf/util/machine.c

@@ -1408,29 +1408,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
 static int add_callchain_ip(struct thread *thread,
 static int add_callchain_ip(struct thread *thread,
 			    struct symbol **parent,
 			    struct symbol **parent,
 			    struct addr_location *root_al,
 			    struct addr_location *root_al,
-			    bool branch_history,
+			    u8 *cpumode,
 			    u64 ip)
 			    u64 ip)
 {
 {
 	struct addr_location al;
 	struct addr_location al;
 
 
 	al.filtered = 0;
 	al.filtered = 0;
 	al.sym = NULL;
 	al.sym = NULL;
-	if (branch_history)
+	if (!cpumode) {
 		thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
 		thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
 						   ip, &al);
 						   ip, &al);
-	else {
-		u8 cpumode = PERF_RECORD_MISC_USER;
-
+	} else {
 		if (ip >= PERF_CONTEXT_MAX) {
 		if (ip >= PERF_CONTEXT_MAX) {
 			switch (ip) {
 			switch (ip) {
 			case PERF_CONTEXT_HV:
 			case PERF_CONTEXT_HV:
-				cpumode = PERF_RECORD_MISC_HYPERVISOR;
+				*cpumode = PERF_RECORD_MISC_HYPERVISOR;
 				break;
 				break;
 			case PERF_CONTEXT_KERNEL:
 			case PERF_CONTEXT_KERNEL:
-				cpumode = PERF_RECORD_MISC_KERNEL;
+				*cpumode = PERF_RECORD_MISC_KERNEL;
 				break;
 				break;
 			case PERF_CONTEXT_USER:
 			case PERF_CONTEXT_USER:
-				cpumode = PERF_RECORD_MISC_USER;
+				*cpumode = PERF_RECORD_MISC_USER;
 				break;
 				break;
 			default:
 			default:
 				pr_debug("invalid callchain context: "
 				pr_debug("invalid callchain context: "
@@ -1444,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread,
 			}
 			}
 			return 0;
 			return 0;
 		}
 		}
-		thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
-				   ip, &al);
+		thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
+					   ip, &al);
 	}
 	}
 
 
 	if (al.sym != NULL) {
 	if (al.sym != NULL) {
@@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
 {
 {
 	struct ip_callchain *chain = sample->callchain;
 	struct ip_callchain *chain = sample->callchain;
 	int chain_nr = min(max_stack, (int)chain->nr);
 	int chain_nr = min(max_stack, (int)chain->nr);
+	u8 cpumode = PERF_RECORD_MISC_USER;
 	int i, j, err;
 	int i, j, err;
 	u64 ip;
 	u64 ip;
 
 
@@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
 					ip = lbr_stack->entries[0].to;
 					ip = lbr_stack->entries[0].to;
 			}
 			}
 
 
-			err = add_callchain_ip(thread, parent, root_al, false, ip);
+			err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
 			if (err)
 			if (err)
 				return (err < 0) ? err : 0;
 				return (err < 0) ? err : 0;
 		}
 		}
@@ -1604,6 +1603,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
 	struct branch_stack *branch = sample->branch_stack;
 	struct branch_stack *branch = sample->branch_stack;
 	struct ip_callchain *chain = sample->callchain;
 	struct ip_callchain *chain = sample->callchain;
 	int chain_nr = min(max_stack, (int)chain->nr);
 	int chain_nr = min(max_stack, (int)chain->nr);
+	u8 cpumode = PERF_RECORD_MISC_USER;
 	int i, j, err;
 	int i, j, err;
 	int skip_idx = -1;
 	int skip_idx = -1;
 	int first_call = 0;
 	int first_call = 0;
@@ -1669,10 +1669,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
 
 
 		for (i = 0; i < nr; i++) {
 		for (i = 0; i < nr; i++) {
 			err = add_callchain_ip(thread, parent, root_al,
 			err = add_callchain_ip(thread, parent, root_al,
-					       true, be[i].to);
+					       NULL, be[i].to);
 			if (!err)
 			if (!err)
 				err = add_callchain_ip(thread, parent, root_al,
 				err = add_callchain_ip(thread, parent, root_al,
-						       true, be[i].from);
+						       NULL, be[i].from);
 			if (err == -EINVAL)
 			if (err == -EINVAL)
 				break;
 				break;
 			if (err)
 			if (err)
@@ -1701,7 +1701,7 @@ check_calls:
 #endif
 #endif
 		ip = chain->ips[j];
 		ip = chain->ips[j];
 
 
-		err = add_callchain_ip(thread, parent, root_al, false, ip);
+		err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
 
 
 		if (err)
 		if (err)
 			return (err < 0) ? err : 0;
 			return (err < 0) ? err : 0;

+ 4 - 17
tools/perf/util/ordered-events.c

@@ -2,7 +2,6 @@
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include "ordered-events.h"
 #include "ordered-events.h"
-#include "evlist.h"
 #include "session.h"
 #include "session.h"
 #include "asm/bug.h"
 #include "asm/bug.h"
 #include "debug.h"
 #include "debug.h"
@@ -167,7 +166,7 @@ int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
 		pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
 		pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
 			   oe->last_flush_type);
 			   oe->last_flush_type);
 
 
-		oe->evlist->stats.nr_unordered_events++;
+		oe->nr_unordered_events++;
 	}
 	}
 
 
 	oevent = ordered_events__new_event(oe, timestamp, event);
 	oevent = ordered_events__new_event(oe, timestamp, event);
@@ -187,7 +186,6 @@ static int __ordered_events__flush(struct ordered_events *oe)
 {
 {
 	struct list_head *head = &oe->events;
 	struct list_head *head = &oe->events;
 	struct ordered_event *tmp, *iter;
 	struct ordered_event *tmp, *iter;
-	struct perf_sample sample;
 	u64 limit = oe->next_flush;
 	u64 limit = oe->next_flush;
 	u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
 	u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
 	bool show_progress = limit == ULLONG_MAX;
 	bool show_progress = limit == ULLONG_MAX;
@@ -206,15 +204,9 @@ static int __ordered_events__flush(struct ordered_events *oe)
 
 
 		if (iter->timestamp > limit)
 		if (iter->timestamp > limit)
 			break;
 			break;
-
-		ret = perf_evlist__parse_sample(oe->evlist, iter->event, &sample);
+		ret = oe->deliver(oe, iter);
 		if (ret)
 		if (ret)
-			pr_err("Can't parse sample, err = %d\n", ret);
-		else {
-			ret = oe->deliver(oe, iter, &sample);
-			if (ret)
-				return ret;
-		}
+			return ret;
 
 
 		ordered_events__delete(oe, iter);
 		ordered_events__delete(oe, iter);
 		oe->last_flush = iter->timestamp;
 		oe->last_flush = iter->timestamp;
@@ -292,18 +284,13 @@ int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
 	return err;
 	return err;
 }
 }
 
 
-void ordered_events__init(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlist, struct perf_tool *tool,
-			  ordered_events__deliver_t deliver)
+void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver)
 {
 {
 	INIT_LIST_HEAD(&oe->events);
 	INIT_LIST_HEAD(&oe->events);
 	INIT_LIST_HEAD(&oe->cache);
 	INIT_LIST_HEAD(&oe->cache);
 	INIT_LIST_HEAD(&oe->to_free);
 	INIT_LIST_HEAD(&oe->to_free);
 	oe->max_alloc_size = (u64) -1;
 	oe->max_alloc_size = (u64) -1;
 	oe->cur_alloc_size = 0;
 	oe->cur_alloc_size = 0;
-	oe->evlist	   = evlist;
-	oe->machines	   = machines;
-	oe->tool	   = tool;
 	oe->deliver	   = deliver;
 	oe->deliver	   = deliver;
 }
 }
 
 

+ 3 - 11
tools/perf/util/ordered-events.h

@@ -3,10 +3,7 @@
 
 
 #include <linux/types.h>
 #include <linux/types.h>
 
 
-struct perf_tool;
-struct perf_evlist;
 struct perf_sample;
 struct perf_sample;
-struct machines;
 
 
 struct ordered_event {
 struct ordered_event {
 	u64			timestamp;
 	u64			timestamp;
@@ -25,8 +22,7 @@ enum oe_flush {
 struct ordered_events;
 struct ordered_events;
 
 
 typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
 typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
-					 struct ordered_event *event,
-					 struct perf_sample *sample);
+					 struct ordered_event *event);
 
 
 struct ordered_events {
 struct ordered_events {
 	u64			last_flush;
 	u64			last_flush;
@@ -39,13 +35,11 @@ struct ordered_events {
 	struct list_head	to_free;
 	struct list_head	to_free;
 	struct ordered_event	*buffer;
 	struct ordered_event	*buffer;
 	struct ordered_event	*last;
 	struct ordered_event	*last;
-	struct machines		*machines;
-	struct perf_evlist	*evlist;
-	struct perf_tool	*tool;
 	ordered_events__deliver_t deliver;
 	ordered_events__deliver_t deliver;
 	int			buffer_idx;
 	int			buffer_idx;
 	unsigned int		nr_events;
 	unsigned int		nr_events;
 	enum oe_flush		last_flush_type;
 	enum oe_flush		last_flush_type;
+	u32			nr_unordered_events;
 	bool                    copy_on_queue;
 	bool                    copy_on_queue;
 };
 };
 
 
@@ -53,9 +47,7 @@ int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
 			  struct perf_sample *sample, u64 file_offset);
 			  struct perf_sample *sample, u64 file_offset);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
 int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
 int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
-void ordered_events__init(struct ordered_events *oe, struct machines *machines,
-			  struct perf_evlist *evlsit, struct perf_tool *tool,
-			  ordered_events__deliver_t deliver);
+void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
 void ordered_events__free(struct ordered_events *oe);
 void ordered_events__free(struct ordered_events *oe);
 
 
 static inline
 static inline

+ 29 - 19
tools/perf/util/session.c

@@ -93,11 +93,20 @@ static void perf_session__set_comm_exec(struct perf_session *session)
 }
 }
 
 
 static int ordered_events__deliver_event(struct ordered_events *oe,
 static int ordered_events__deliver_event(struct ordered_events *oe,
-					 struct ordered_event *event,
-					 struct perf_sample *sample)
+					 struct ordered_event *event)
 {
 {
-	return machines__deliver_event(oe->machines, oe->evlist, event->event,
-				       sample, oe->tool, event->file_offset);
+	struct perf_sample sample;
+	struct perf_session *session = container_of(oe, struct perf_session,
+						    ordered_events);
+	int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
+
+	if (ret) {
+		pr_err("Can't parse sample, err = %d\n", ret);
+		return ret;
+	}
+
+	return machines__deliver_event(&session->machines, session->evlist, event->event,
+				       &sample, session->tool, event->file_offset);
 }
 }
 
 
 struct perf_session *perf_session__new(struct perf_data_file *file,
 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,
 		goto out;
 		goto out;
 
 
 	session->repipe = repipe;
 	session->repipe = repipe;
+	session->tool   = tool;
 	machines__init(&session->machines);
 	machines__init(&session->machines);
+	ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
 
 
 	if (file) {
 	if (file) {
 		if (perf_data_file__open(file))
 		if (perf_data_file__open(file))
@@ -139,9 +150,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 	    tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
 	    tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
 		tool->ordered_events = false;
 		tool->ordered_events = false;
-	} else {
-		ordered_events__init(&session->ordered_events, &session->machines,
-				     session->evlist, tool, ordered_events__deliver_event);
 	}
 	}
 
 
 	return session;
 	return session;
@@ -941,7 +949,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 					    u64 file_offset)
 					    u64 file_offset)
 {
 {
 	struct ordered_events *oe = &session->ordered_events;
 	struct ordered_events *oe = &session->ordered_events;
-	struct perf_tool *tool = oe->tool;
+	struct perf_tool *tool = session->tool;
 	int fd = perf_data_file__fd(session->file);
 	int fd = perf_data_file__fd(session->file);
 	int err;
 	int err;
 
 
@@ -982,7 +990,7 @@ int perf_session__deliver_synth_event(struct perf_session *session,
 				      struct perf_sample *sample)
 				      struct perf_sample *sample)
 {
 {
 	struct perf_evlist *evlist = session->evlist;
 	struct perf_evlist *evlist = session->evlist;
-	struct perf_tool *tool = session->ordered_events.tool;
+	struct perf_tool *tool = session->tool;
 
 
 	events_stats__inc(&evlist->stats, event->header.type);
 	events_stats__inc(&evlist->stats, event->header.type);
 
 
@@ -1060,7 +1068,7 @@ static s64 perf_session__process_event(struct perf_session *session,
 				       union perf_event *event, u64 file_offset)
 				       union perf_event *event, u64 file_offset)
 {
 {
 	struct perf_evlist *evlist = session->evlist;
 	struct perf_evlist *evlist = session->evlist;
-	struct perf_tool *tool = session->ordered_events.tool;
+	struct perf_tool *tool = session->tool;
 	struct perf_sample sample;
 	struct perf_sample sample;
 	int ret;
 	int ret;
 
 
@@ -1117,10 +1125,12 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
 	return thread;
 	return thread;
 }
 }
 
 
-static void perf_tool__warn_about_errors(const struct perf_tool *tool,
-					 const struct events_stats *stats)
+static void perf_session__warn_about_errors(const struct perf_session *session)
 {
 {
-	if (tool->lost == perf_event__process_lost &&
+	const struct events_stats *stats = &session->evlist->stats;
+	const struct ordered_events *oe = &session->ordered_events;
+
+	if (session->tool->lost == perf_event__process_lost &&
 	    stats->nr_events[PERF_RECORD_LOST] != 0) {
 	    stats->nr_events[PERF_RECORD_LOST] != 0) {
 		ui__warning("Processed %d events and lost %d chunks!\n\n"
 		ui__warning("Processed %d events and lost %d chunks!\n\n"
 			    "Check IO/CPU overload!\n\n",
 			    "Check IO/CPU overload!\n\n",
@@ -1156,8 +1166,8 @@ static void perf_tool__warn_about_errors(const struct perf_tool *tool,
 			    stats->nr_unprocessable_samples);
 			    stats->nr_unprocessable_samples);
 	}
 	}
 
 
-	if (stats->nr_unordered_events != 0)
-		ui__warning("%u out of order events recorded.\n", stats->nr_unordered_events);
+	if (oe->nr_unordered_events != 0)
+		ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
 }
 }
 
 
 volatile int session_done;
 volatile int session_done;
@@ -1165,7 +1175,7 @@ volatile int session_done;
 static int __perf_session__process_pipe_events(struct perf_session *session)
 static int __perf_session__process_pipe_events(struct perf_session *session)
 {
 {
 	struct ordered_events *oe = &session->ordered_events;
 	struct ordered_events *oe = &session->ordered_events;
-	struct perf_tool *tool = oe->tool;
+	struct perf_tool *tool = session->tool;
 	int fd = perf_data_file__fd(session->file);
 	int fd = perf_data_file__fd(session->file);
 	union perf_event *event;
 	union perf_event *event;
 	uint32_t size, cur_size = 0;
 	uint32_t size, cur_size = 0;
@@ -1248,7 +1258,7 @@ done:
 	err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 	err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 out_err:
 out_err:
 	free(buf);
 	free(buf);
-	perf_tool__warn_about_errors(tool, &session->evlist->stats);
+	perf_session__warn_about_errors(session);
 	ordered_events__free(&session->ordered_events);
 	ordered_events__free(&session->ordered_events);
 	return err;
 	return err;
 }
 }
@@ -1298,7 +1308,7 @@ static int __perf_session__process_events(struct perf_session *session,
 					  u64 file_size)
 					  u64 file_size)
 {
 {
 	struct ordered_events *oe = &session->ordered_events;
 	struct ordered_events *oe = &session->ordered_events;
-	struct perf_tool *tool = oe->tool;
+	struct perf_tool *tool = session->tool;
 	int fd = perf_data_file__fd(session->file);
 	int fd = perf_data_file__fd(session->file);
 	u64 head, page_offset, file_offset, file_pos, size;
 	u64 head, page_offset, file_offset, file_pos, size;
 	int err, mmap_prot, mmap_flags, map_idx = 0;
 	int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1394,7 +1404,7 @@ out:
 	err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 	err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 out_err:
 out_err:
 	ui_progress__finish();
 	ui_progress__finish();
-	perf_tool__warn_about_errors(tool, &session->evlist->stats);
+	perf_session__warn_about_errors(session);
 	ordered_events__free(&session->ordered_events);
 	ordered_events__free(&session->ordered_events);
 	session->one_mmap = false;
 	session->one_mmap = false;
 	return err;
 	return err;

+ 1 - 0
tools/perf/util/session.h

@@ -26,6 +26,7 @@ struct perf_session {
 	u64			one_mmap_offset;
 	u64			one_mmap_offset;
 	struct ordered_events	ordered_events;
 	struct ordered_events	ordered_events;
 	struct perf_data_file	*file;
 	struct perf_data_file	*file;
+	struct perf_tool	*tool;
 };
 };
 
 
 #define PRINT_IP_OPT_IP		(1<<0)
 #define PRINT_IP_OPT_IP		(1<<0)