diff options
author | David Ahern <dsahern@gmail.com> | 2015-03-30 16:35:58 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-03-31 16:52:30 -0400 |
commit | ca6c41c59b964d362823e80442e9e32c31106b29 (patch) | |
tree | dd65c1b83e3a5c1b7efe08cfbc28370ecd7337f3 /tools | |
parent | 5aa0b030e8d29d6719c144818814b519cfcb105c (diff) |
perf tools: Fix ppid for synthesized fork events
363b785f38 added synthesized fork events and set a thread's parent id to
itself. Since we are already processing /proc/<pid>/status the ppid can
be determined properly. Make it so.
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Mario <jmario@redhat.com>
Link: http://lkml.kernel.org/r/1427747758-18510-2-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/event.c | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 023dd3548a94..5516236df6ab 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = { | |||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Assumes that the first 4095 bytes of /proc/pid/stat contains | 53 | * Assumes that the first 4095 bytes of /proc/pid/stat contains |
54 | * the comm and tgid. | 54 | * the comm, tgid and ppid. |
55 | */ | 55 | */ |
56 | static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | 56 | static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len, |
57 | pid_t *tgid, pid_t *ppid) | ||
57 | { | 58 | { |
58 | char filename[PATH_MAX]; | 59 | char filename[PATH_MAX]; |
59 | char bf[4096]; | 60 | char bf[4096]; |
60 | int fd; | 61 | int fd; |
61 | size_t size = 0, n; | 62 | size_t size = 0, n; |
62 | pid_t tgid = -1; | 63 | char *nl, *name, *tgids, *ppids; |
63 | char *nl, *name, *tgids; | 64 | |
65 | *tgid = -1; | ||
66 | *ppid = -1; | ||
64 | 67 | ||
65 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | 68 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); |
66 | 69 | ||
67 | fd = open(filename, O_RDONLY); | 70 | fd = open(filename, O_RDONLY); |
68 | if (fd < 0) { | 71 | if (fd < 0) { |
69 | pr_debug("couldn't open %s\n", filename); | 72 | pr_debug("couldn't open %s\n", filename); |
70 | return 0; | 73 | return -1; |
71 | } | 74 | } |
72 | 75 | ||
73 | n = read(fd, bf, sizeof(bf) - 1); | 76 | n = read(fd, bf, sizeof(bf) - 1); |
74 | close(fd); | 77 | close(fd); |
75 | if (n <= 0) { | 78 | if (n <= 0) { |
76 | pr_warning("Couldn't get COMM and tgid for pid %d\n", | 79 | pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n", |
77 | pid); | 80 | pid); |
78 | return -1; | 81 | return -1; |
79 | } | 82 | } |
@@ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | |||
81 | 84 | ||
82 | name = strstr(bf, "Name:"); | 85 | name = strstr(bf, "Name:"); |
83 | tgids = strstr(bf, "Tgid:"); | 86 | tgids = strstr(bf, "Tgid:"); |
87 | ppids = strstr(bf, "PPid:"); | ||
84 | 88 | ||
85 | if (name) { | 89 | if (name) { |
86 | name += 5; /* strlen("Name:") */ | 90 | name += 5; /* strlen("Name:") */ |
@@ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | |||
103 | 107 | ||
104 | if (tgids) { | 108 | if (tgids) { |
105 | tgids += 5; /* strlen("Tgid:") */ | 109 | tgids += 5; /* strlen("Tgid:") */ |
106 | tgid = atoi(tgids); | 110 | *tgid = atoi(tgids); |
107 | } else { | 111 | } else { |
108 | pr_debug("Tgid: string not found for pid %d\n", pid); | 112 | pr_debug("Tgid: string not found for pid %d\n", pid); |
109 | } | 113 | } |
110 | 114 | ||
111 | 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; | ||
112 | } | 123 | } |
113 | 124 | ||
114 | static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | 125 | static int perf_event__prepare_comm(union perf_event *event, pid_t pid, |
115 | struct machine *machine) | 126 | struct machine *machine, |
127 | pid_t *tgid, pid_t *ppid) | ||
116 | { | 128 | { |
117 | size_t size; | 129 | size_t size; |
118 | pid_t tgid; | 130 | |
131 | *ppid = -1; | ||
119 | 132 | ||
120 | memset(&event->comm, 0, sizeof(event->comm)); | 133 | memset(&event->comm, 0, sizeof(event->comm)); |
121 | 134 | ||
122 | if (machine__is_host(machine)) | 135 | if (machine__is_host(machine)) { |
123 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | 136 | if (perf_event__get_comm_ids(pid, event->comm.comm, |
124 | sizeof(event->comm.comm)); | 137 | sizeof(event->comm.comm), |
125 | else | 138 | tgid, ppid) != 0) { |
126 | tgid = machine->pid; | 139 | return -1; |
140 | } | ||
141 | } else { | ||
142 | *tgid = machine->pid; | ||
143 | } | ||
127 | 144 | ||
128 | if (tgid < 0) | 145 | if (*tgid < 0) |
129 | goto out; | 146 | return -1; |
130 | 147 | ||
131 | event->comm.pid = tgid; | 148 | event->comm.pid = *tgid; |
132 | event->comm.header.type = PERF_RECORD_COMM; | 149 | event->comm.header.type = PERF_RECORD_COMM; |
133 | 150 | ||
134 | size = strlen(event->comm.comm) + 1; | 151 | size = strlen(event->comm.comm) + 1; |
@@ -138,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | |||
138 | (sizeof(event->comm.comm) - size) + | 155 | (sizeof(event->comm.comm) - size) + |
139 | machine->id_hdr_size); | 156 | machine->id_hdr_size); |
140 | event->comm.tid = pid; | 157 | event->comm.tid = pid; |
141 | out: | 158 | |
142 | return tgid; | 159 | return 0; |
143 | } | 160 | } |
144 | 161 | ||
145 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | 162 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, |
@@ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | |||
147 | perf_event__handler_t process, | 164 | perf_event__handler_t process, |
148 | struct machine *machine) | 165 | struct machine *machine) |
149 | { | 166 | { |
150 | pid_t tgid = perf_event__prepare_comm(event, pid, machine); | 167 | pid_t tgid, ppid; |
151 | 168 | ||
152 | if (tgid == -1) | 169 | if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0) |
153 | goto out; | 170 | return -1; |
154 | 171 | ||
155 | if (process(tool, event, &synth_sample, machine) != 0) | 172 | if (process(tool, event, &synth_sample, machine) != 0) |
156 | return -1; | 173 | return -1; |
157 | 174 | ||
158 | out: | ||
159 | return tgid; | 175 | return tgid; |
160 | } | 176 | } |
161 | 177 | ||
162 | static int perf_event__synthesize_fork(struct perf_tool *tool, | 178 | static int perf_event__synthesize_fork(struct perf_tool *tool, |
163 | union perf_event *event, pid_t pid, | 179 | union perf_event *event, |
164 | pid_t tgid, perf_event__handler_t process, | 180 | pid_t pid, pid_t tgid, pid_t ppid, |
181 | perf_event__handler_t process, | ||
165 | struct machine *machine) | 182 | struct machine *machine) |
166 | { | 183 | { |
167 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); | 184 | memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); |
168 | 185 | ||
169 | event->fork.ppid = tgid; | 186 | event->fork.ppid = ppid; |
170 | event->fork.ptid = tgid; | 187 | event->fork.ptid = ppid; |
171 | event->fork.pid = tgid; | 188 | event->fork.pid = tgid; |
172 | event->fork.tid = pid; | 189 | event->fork.tid = pid; |
173 | event->fork.header.type = PERF_RECORD_FORK; | 190 | event->fork.header.type = PERF_RECORD_FORK; |
@@ -359,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
359 | char filename[PATH_MAX]; | 376 | char filename[PATH_MAX]; |
360 | DIR *tasks; | 377 | DIR *tasks; |
361 | struct dirent dirent, *next; | 378 | struct dirent dirent, *next; |
362 | pid_t tgid; | 379 | pid_t tgid, ppid; |
363 | 380 | ||
364 | /* special case: only send one comm event using passed in pid */ | 381 | /* special case: only send one comm event using passed in pid */ |
365 | if (!full) { | 382 | if (!full) { |
@@ -394,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
394 | if (*end) | 411 | if (*end) |
395 | continue; | 412 | continue; |
396 | 413 | ||
397 | tgid = perf_event__prepare_comm(comm_event, _pid, machine); | 414 | if (perf_event__prepare_comm(comm_event, _pid, machine, |
398 | if (tgid == -1) | 415 | &tgid, &ppid) != 0) |
399 | return -1; | 416 | return -1; |
400 | 417 | ||
401 | if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, | 418 | if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, |
402 | process, machine) < 0) | 419 | ppid, process, machine) < 0) |
403 | return -1; | 420 | return -1; |
404 | /* | 421 | /* |
405 | * Send the prepared comm event | 422 | * Send the prepared comm event |