Skip to content

Commit aaa9fa3

Browse files
author
Ingo Molnar
committed
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 <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
2 parents ccd41c8 + 9870d78 commit aaa9fa3

File tree

9 files changed

+144
-123
lines changed

9 files changed

+144
-123
lines changed

tools/perf/Makefile.perf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ include config/utilities.mak
6969
#
7070
# Define NO_ZLIB if you do not want to support compressed kernel modules
7171
#
72-
# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
72+
# Define LIBBABELTRACE if you DO want libbabeltrace support
7373
# for CTF data format.
7474
#
7575
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules

tools/perf/config/Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ ifndef NO_LIBELF
9595
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
9696
endif
9797

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

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

tools/perf/util/event.c

Lines changed: 90 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -49,70 +49,103 @@ static struct perf_sample synth_sample = {
4949
.period = 1,
5050
};
5151

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)
5358
{
5459
char filename[PATH_MAX];
55-
char bf[BUFSIZ];
56-
FILE *fp;
57-
size_t size = 0;
58-
pid_t tgid = -1;
60+
char bf[4096];
61+
int fd;
62+
size_t size = 0, n;
63+
char *nl, *name, *tgids, *ppids;
64+
65+
*tgid = -1;
66+
*ppid = -1;
5967

6068
snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
6169

62-
fp = fopen(filename, "r");
63-
if (fp == NULL) {
70+
fd = open(filename, O_RDONLY);
71+
if (fd < 0) {
6472
pr_debug("couldn't open %s\n", filename);
65-
return 0;
73+
return -1;
6674
}
6775

68-
while (!comm[0] || (tgid < 0)) {
69-
if (fgets(bf, sizeof(bf), fp) == NULL) {
70-
pr_warning("couldn't get COMM and pgid, malformed %s\n",
71-
filename);
72-
break;
73-
}
76+
n = read(fd, bf, sizeof(bf) - 1);
77+
close(fd);
78+
if (n <= 0) {
79+
pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
80+
pid);
81+
return -1;
82+
}
83+
bf[n] = '\0';
7484

75-
if (memcmp(bf, "Name:", 5) == 0) {
76-
char *name = bf + 5;
77-
while (*name && isspace(*name))
78-
++name;
79-
size = strlen(name) - 1;
80-
if (size >= len)
81-
size = len - 1;
82-
memcpy(comm, name, size);
83-
comm[size] = '\0';
84-
85-
} else if (memcmp(bf, "Tgid:", 5) == 0) {
86-
char *tgids = bf + 5;
87-
while (*tgids && isspace(*tgids))
88-
++tgids;
89-
tgid = atoi(tgids);
90-
}
85+
name = strstr(bf, "Name:");
86+
tgids = strstr(bf, "Tgid:");
87+
ppids = strstr(bf, "PPid:");
88+
89+
if (name) {
90+
name += 5; /* strlen("Name:") */
91+
92+
while (*name && isspace(*name))
93+
++name;
94+
95+
nl = strchr(name, '\n');
96+
if (nl)
97+
*nl = '\0';
98+
99+
size = strlen(name);
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);
91106
}
92107

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+
}
94114

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;
96123
}
97124

98-
static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
99-
struct machine *machine)
125+
static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
126+
struct machine *machine,
127+
pid_t *tgid, pid_t *ppid)
100128
{
101129
size_t size;
102-
pid_t tgid;
130+
131+
*ppid = -1;
103132

104133
memset(&event->comm, 0, sizeof(event->comm));
105134

106-
if (machine__is_host(machine))
107-
tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
108-
sizeof(event->comm.comm));
109-
else
110-
tgid = machine->pid;
135+
if (machine__is_host(machine)) {
136+
if (perf_event__get_comm_ids(pid, event->comm.comm,
137+
sizeof(event->comm.comm),
138+
tgid, ppid) != 0) {
139+
return -1;
140+
}
141+
} else {
142+
*tgid = machine->pid;
143+
}
111144

112-
if (tgid < 0)
113-
goto out;
145+
if (*tgid < 0)
146+
return -1;
114147

115-
event->comm.pid = tgid;
148+
event->comm.pid = *tgid;
116149
event->comm.header.type = PERF_RECORD_COMM;
117150

118151
size = strlen(event->comm.comm) + 1;
@@ -122,36 +155,36 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
122155
(sizeof(event->comm.comm) - size) +
123156
machine->id_hdr_size);
124157
event->comm.tid = pid;
125-
out:
126-
return tgid;
158+
159+
return 0;
127160
}
128161

129162
static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
130163
union perf_event *event, pid_t pid,
131164
perf_event__handler_t process,
132165
struct machine *machine)
133166
{
134-
pid_t tgid = perf_event__prepare_comm(event, pid, machine);
167+
pid_t tgid, ppid;
135168

136-
if (tgid == -1)
137-
goto out;
169+
if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
170+
return -1;
138171

139172
if (process(tool, event, &synth_sample, machine) != 0)
140173
return -1;
141174

142-
out:
143175
return tgid;
144176
}
145177

146178
static int perf_event__synthesize_fork(struct perf_tool *tool,
147-
union perf_event *event, pid_t pid,
148-
pid_t tgid, perf_event__handler_t process,
179+
union perf_event *event,
180+
pid_t pid, pid_t tgid, pid_t ppid,
181+
perf_event__handler_t process,
149182
struct machine *machine)
150183
{
151184
memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
152185

153-
event->fork.ppid = tgid;
154-
event->fork.ptid = tgid;
186+
event->fork.ppid = ppid;
187+
event->fork.ptid = ppid;
155188
event->fork.pid = tgid;
156189
event->fork.tid = pid;
157190
event->fork.header.type = PERF_RECORD_FORK;
@@ -343,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
343376
char filename[PATH_MAX];
344377
DIR *tasks;
345378
struct dirent dirent, *next;
346-
pid_t tgid;
379+
pid_t tgid, ppid;
347380

348381
/* special case: only send one comm event using passed in pid */
349382
if (!full) {
@@ -378,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
378411
if (*end)
379412
continue;
380413

381-
tgid = perf_event__prepare_comm(comm_event, _pid, machine);
382-
if (tgid == -1)
414+
if (perf_event__prepare_comm(comm_event, _pid, machine,
415+
&tgid, &ppid) != 0)
383416
return -1;
384417

385418
if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
386-
process, machine) < 0)
419+
ppid, process, machine) < 0)
387420
return -1;
388421
/*
389422
* Send the prepared comm event

tools/perf/util/event.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ struct events_stats {
242242
u32 nr_invalid_chains;
243243
u32 nr_unknown_id;
244244
u32 nr_unprocessable_samples;
245-
u32 nr_unordered_events;
246245
};
247246

248247
struct attr_event {

tools/perf/util/machine.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,29 +1408,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
14081408
static int add_callchain_ip(struct thread *thread,
14091409
struct symbol **parent,
14101410
struct addr_location *root_al,
1411-
bool branch_history,
1411+
u8 *cpumode,
14121412
u64 ip)
14131413
{
14141414
struct addr_location al;
14151415

14161416
al.filtered = 0;
14171417
al.sym = NULL;
1418-
if (branch_history)
1418+
if (!cpumode) {
14191419
thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
14201420
ip, &al);
1421-
else {
1422-
u8 cpumode = PERF_RECORD_MISC_USER;
1423-
1421+
} else {
14241422
if (ip >= PERF_CONTEXT_MAX) {
14251423
switch (ip) {
14261424
case PERF_CONTEXT_HV:
1427-
cpumode = PERF_RECORD_MISC_HYPERVISOR;
1425+
*cpumode = PERF_RECORD_MISC_HYPERVISOR;
14281426
break;
14291427
case PERF_CONTEXT_KERNEL:
1430-
cpumode = PERF_RECORD_MISC_KERNEL;
1428+
*cpumode = PERF_RECORD_MISC_KERNEL;
14311429
break;
14321430
case PERF_CONTEXT_USER:
1433-
cpumode = PERF_RECORD_MISC_USER;
1431+
*cpumode = PERF_RECORD_MISC_USER;
14341432
break;
14351433
default:
14361434
pr_debug("invalid callchain context: "
@@ -1444,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread,
14441442
}
14451443
return 0;
14461444
}
1447-
thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1448-
ip, &al);
1445+
thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
1446+
ip, &al);
14491447
}
14501448

14511449
if (al.sym != NULL) {
@@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
15381536
{
15391537
struct ip_callchain *chain = sample->callchain;
15401538
int chain_nr = min(max_stack, (int)chain->nr);
1539+
u8 cpumode = PERF_RECORD_MISC_USER;
15411540
int i, j, err;
15421541
u64 ip;
15431542

@@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
15841583
ip = lbr_stack->entries[0].to;
15851584
}
15861585

1587-
err = add_callchain_ip(thread, parent, root_al, false, ip);
1586+
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
15881587
if (err)
15891588
return (err < 0) ? err : 0;
15901589
}
@@ -1604,6 +1603,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
16041603
struct branch_stack *branch = sample->branch_stack;
16051604
struct ip_callchain *chain = sample->callchain;
16061605
int chain_nr = min(max_stack, (int)chain->nr);
1606+
u8 cpumode = PERF_RECORD_MISC_USER;
16071607
int i, j, err;
16081608
int skip_idx = -1;
16091609
int first_call = 0;
@@ -1669,10 +1669,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
16691669

16701670
for (i = 0; i < nr; i++) {
16711671
err = add_callchain_ip(thread, parent, root_al,
1672-
true, be[i].to);
1672+
NULL, be[i].to);
16731673
if (!err)
16741674
err = add_callchain_ip(thread, parent, root_al,
1675-
true, be[i].from);
1675+
NULL, be[i].from);
16761676
if (err == -EINVAL)
16771677
break;
16781678
if (err)
@@ -1701,7 +1701,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
17011701
#endif
17021702
ip = chain->ips[j];
17031703

1704-
err = add_callchain_ip(thread, parent, root_al, false, ip);
1704+
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
17051705

17061706
if (err)
17071707
return (err < 0) ? err : 0;

0 commit comments

Comments
 (0)