Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaa9fa38 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ccd41c86 9870d780
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ include config/utilities.mak
#
# 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.
#
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
+2 −3
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ ifndef NO_LIBELF
  FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif

ifndef NO_LIBBABELTRACE
ifdef LIBBABELTRACE
  # for linking with debug library, run like:
  # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
  ifdef LIBBABELTRACE_DIR
@@ -598,7 +598,7 @@ else
  NO_PERF_READ_VDSOX32 := 1
endif

ifndef NO_LIBBABELTRACE
ifdef LIBBABELTRACE
  $(call feature_check,libbabeltrace)
  ifeq ($(feature-libbabeltrace), 1)
    CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
@@ -607,7 +607,6 @@ ifndef NO_LIBBABELTRACE
    $(call detected,CONFIG_LIBBABELTRACE)
  else
    msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
    NO_LIBBABELTRACE := 1
  endif
endif

+90 −57
Original line number Diff line number Diff line
@@ -49,70 +49,103 @@ static struct perf_sample synth_sample = {
	.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 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);

	fp = fopen(filename, "r");
	if (fp == NULL) {
	fd = open(filename, O_RDONLY);
	if (fd < 0) {
		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';

	name = strstr(bf, "Name:");
	tgids = strstr(bf, "Tgid:");
	ppids = strstr(bf, "PPid:");

	if (name) {
		name += 5;  /* strlen("Name:") */

		if (memcmp(bf, "Name:", 5) == 0) {
			char *name = bf + 5;
		while (*name && isspace(*name))
			++name;
			size = strlen(name) - 1;

		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 if (memcmp(bf, "Tgid:", 5) == 0) {
			char *tgids = bf + 5;
			while (*tgids && isspace(*tgids))
				++tgids;
			tgid = atoi(tgids);
	} else {
		pr_debug("Name: string not found for pid %d\n", pid);
	}

	if (tgids) {
		tgids += 5;  /* strlen("Tgid:") */
		*tgid = atoi(tgids);
	} else {
		pr_debug("Tgid: string not found for pid %d\n", pid);
	}

	fclose(fp);
	if (ppids) {
		ppids += 5;  /* strlen("PPid:") */
		*ppid = atoi(ppids);
	} else {
		pr_debug("PPid: string not found for pid %d\n", pid);
	}

	return tgid;
	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;
	pid_t tgid;

	*ppid = -1;

	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;

	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) +
				machine->id_hdr_size);
	event->comm.tid = pid;
out:
	return tgid;

	return 0;
}

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,
					 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)
		return -1;

out:
	return tgid;
}

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)
{
	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.tid  = pid;
	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];
	DIR *tasks;
	struct dirent dirent, *next;
	pid_t tgid;
	pid_t tgid, ppid;

	/* special case: only send one comm event using passed in pid */
	if (!full) {
@@ -378,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
		if (*end)
			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;

		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
						process, machine) < 0)
						ppid, process, machine) < 0)
			return -1;
		/*
		 * Send the prepared comm event
+0 −1
Original line number Diff line number Diff line
@@ -242,7 +242,6 @@ struct events_stats {
	u32 nr_invalid_chains;
	u32 nr_unknown_id;
	u32 nr_unprocessable_samples;
	u32 nr_unordered_events;
};

struct attr_event {
+14 −14
Original line number Diff line number Diff line
@@ -1408,29 +1408,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
static int add_callchain_ip(struct thread *thread,
			    struct symbol **parent,
			    struct addr_location *root_al,
			    bool branch_history,
			    u8 *cpumode,
			    u64 ip)
{
	struct addr_location al;

	al.filtered = 0;
	al.sym = NULL;
	if (branch_history)
	if (!cpumode) {
		thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
						   ip, &al);
	else {
		u8 cpumode = PERF_RECORD_MISC_USER;

	} else {
		if (ip >= PERF_CONTEXT_MAX) {
			switch (ip) {
			case PERF_CONTEXT_HV:
				cpumode = PERF_RECORD_MISC_HYPERVISOR;
				*cpumode = PERF_RECORD_MISC_HYPERVISOR;
				break;
			case PERF_CONTEXT_KERNEL:
				cpumode = PERF_RECORD_MISC_KERNEL;
				*cpumode = PERF_RECORD_MISC_KERNEL;
				break;
			case PERF_CONTEXT_USER:
				cpumode = PERF_RECORD_MISC_USER;
				*cpumode = PERF_RECORD_MISC_USER;
				break;
			default:
				pr_debug("invalid callchain context: "
@@ -1444,7 +1442,7 @@ static int add_callchain_ip(struct thread *thread,
			}
			return 0;
		}
		thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
		thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
					   ip, &al);
	}

@@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
{
	struct ip_callchain *chain = sample->callchain;
	int chain_nr = min(max_stack, (int)chain->nr);
	u8 cpumode = PERF_RECORD_MISC_USER;
	int i, j, err;
	u64 ip;

@@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
					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)
				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 ip_callchain *chain = sample->callchain;
	int chain_nr = min(max_stack, (int)chain->nr);
	u8 cpumode = PERF_RECORD_MISC_USER;
	int i, j, err;
	int skip_idx = -1;
	int first_call = 0;
@@ -1669,10 +1669,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,

		for (i = 0; i < nr; i++) {
			err = add_callchain_ip(thread, parent, root_al,
					       true, be[i].to);
					       NULL, be[i].to);
			if (!err)
				err = add_callchain_ip(thread, parent, root_al,
						       true, be[i].from);
						       NULL, be[i].from);
			if (err == -EINVAL)
				break;
			if (err)
@@ -1701,7 +1701,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
#endif
		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)
			return (err < 0) ? err : 0;
Loading