summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-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
#
# 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
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
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
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 = {
.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';
- 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;
- 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
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 {
u32 nr_invalid_chains;
u32 nr_unknown_id;
u32 nr_unprocessable_samples;
- u32 nr_unordered_events;
};
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,
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,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread,
}
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) {
@@ -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 @@ check_calls:
#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;
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 @@
#include <linux/compiler.h>
#include <linux/string.h>
#include "ordered-events.h"
-#include "evlist.h"
#include "session.h"
#include "asm/bug.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",
oe->last_flush_type);
- oe->evlist->stats.nr_unordered_events++;
+ oe->nr_unordered_events++;
}
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 ordered_event *tmp, *iter;
- struct perf_sample sample;
u64 limit = oe->next_flush;
u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
bool show_progress = limit == ULLONG_MAX;
@@ -206,15 +204,9 @@ static int __ordered_events__flush(struct ordered_events *oe)
if (iter->timestamp > limit)
break;
-
- ret = perf_evlist__parse_sample(oe->evlist, iter->event, &sample);
+ ret = oe->deliver(oe, iter);
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);
oe->last_flush = iter->timestamp;
@@ -292,18 +284,13 @@ int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
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->cache);
INIT_LIST_HEAD(&oe->to_free);
oe->max_alloc_size = (u64) -1;
oe->cur_alloc_size = 0;
- oe->evlist = evlist;
- oe->machines = machines;
- oe->tool = tool;
oe->deliver = deliver;
}
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 @@
#include <linux/types.h>
-struct perf_tool;
-struct perf_evlist;
struct perf_sample;
-struct machines;
struct ordered_event {
u64 timestamp;
@@ -25,8 +22,7 @@ enum oe_flush {
struct ordered_events;
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 {
u64 last_flush;
@@ -39,13 +35,11 @@ struct ordered_events {
struct list_head to_free;
struct ordered_event *buffer;
struct ordered_event *last;
- struct machines *machines;
- struct perf_evlist *evlist;
- struct perf_tool *tool;
ordered_events__deliver_t deliver;
int buffer_idx;
unsigned int nr_events;
enum oe_flush last_flush_type;
+ u32 nr_unordered_events;
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);
void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
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);
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)
}
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,
@@ -109,7 +118,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
goto out;
session->repipe = repipe;
+ session->tool = tool;
machines__init(&session->machines);
+ ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
if (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)) {
dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
tool->ordered_events = false;
- } else {
- ordered_events__init(&session->ordered_events, &session->machines,
- session->evlist, tool, ordered_events__deliver_event);
}
return session;
@@ -941,7 +949,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
u64 file_offset)
{
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 err;
@@ -982,7 +990,7 @@ int perf_session__deliver_synth_event(struct perf_session *session,
struct perf_sample *sample)
{
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);
@@ -1060,7 +1068,7 @@ static s64 perf_session__process_event(struct perf_session *session,
union perf_event *event, u64 file_offset)
{
struct perf_evlist *evlist = session->evlist;
- struct perf_tool *tool = session->ordered_events.tool;
+ struct perf_tool *tool = session->tool;
struct perf_sample sample;
int ret;
@@ -1117,10 +1125,12 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
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) {
ui__warning("Processed %d events and lost %d chunks!\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);
}
- 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;
@@ -1165,7 +1175,7 @@ volatile int session_done;
static int __perf_session__process_pipe_events(struct perf_session *session)
{
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);
union perf_event *event;
uint32_t size, cur_size = 0;
@@ -1248,7 +1258,7 @@ done:
err = ordered_events__flush(oe, OE_FLUSH__FINAL);
out_err:
free(buf);
- perf_tool__warn_about_errors(tool, &session->evlist->stats);
+ perf_session__warn_about_errors(session);
ordered_events__free(&session->ordered_events);
return err;
}
@@ -1298,7 +1308,7 @@ static int __perf_session__process_events(struct perf_session *session,
u64 file_size)
{
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);
u64 head, page_offset, file_offset, file_pos, size;
int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1394,7 +1404,7 @@ out:
err = ordered_events__flush(oe, OE_FLUSH__FINAL);
out_err:
ui_progress__finish();
- perf_tool__warn_about_errors(tool, &session->evlist->stats);
+ perf_session__warn_about_errors(session);
ordered_events__free(&session->ordered_events);
session->one_mmap = false;
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 {
u64 one_mmap_offset;
struct ordered_events ordered_events;
struct perf_data_file *file;
+ struct perf_tool *tool;
};
#define PRINT_IP_OPT_IP (1<<0)