diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-08-11 15:22:00 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-12 08:10:48 -0400 |
commit | 2a8083f063472f27c253545dd64e1a7bbbb1ab61 (patch) | |
tree | 78c20465589a102a4c28357c8207ea3366cfff69 | |
parent | f64ccccb8afa43abdd63fcbd230f818d6ea0883f (diff) |
perf record: Fix .tid and .pid fill-in when synthesizing events
Noticed when trying to record events for a firefox thread. We
were synthesizing both .tid and .pid with the pid passed via
--pid.
Fix it by reading /proc/PID/status and getting the tgid
to use in .pid, .tid gets the specified "pid".
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090811192200.GF18061@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | tools/perf/builtin-record.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0345aad8eba5..30b83def03d4 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -203,46 +203,48 @@ static void sig_atexit(void) | |||
203 | kill(getpid(), signr); | 203 | kill(getpid(), signr); |
204 | } | 204 | } |
205 | 205 | ||
206 | static void pid_synthesize_comm_event(pid_t pid, int full) | 206 | static pid_t pid_synthesize_comm_event(pid_t pid, int full) |
207 | { | 207 | { |
208 | struct comm_event comm_ev; | 208 | struct comm_event comm_ev; |
209 | char filename[PATH_MAX]; | 209 | char filename[PATH_MAX]; |
210 | char bf[BUFSIZ]; | 210 | char bf[BUFSIZ]; |
211 | int fd; | 211 | FILE *fp; |
212 | size_t size; | 212 | size_t size = 0; |
213 | char *field, *sep; | ||
214 | DIR *tasks; | 213 | DIR *tasks; |
215 | struct dirent dirent, *next; | 214 | struct dirent dirent, *next; |
215 | pid_t tgid = 0; | ||
216 | 216 | ||
217 | snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); | 217 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); |
218 | 218 | ||
219 | fd = open(filename, O_RDONLY); | 219 | fp = fopen(filename, "r"); |
220 | if (fd < 0) { | 220 | if (fd == NULL) { |
221 | /* | 221 | /* |
222 | * We raced with a task exiting - just return: | 222 | * We raced with a task exiting - just return: |
223 | */ | 223 | */ |
224 | if (verbose) | 224 | if (verbose) |
225 | fprintf(stderr, "couldn't open %s\n", filename); | 225 | fprintf(stderr, "couldn't open %s\n", filename); |
226 | return; | 226 | return 0; |
227 | } | 227 | } |
228 | if (read(fd, bf, sizeof(bf)) < 0) { | ||
229 | fprintf(stderr, "couldn't read %s\n", filename); | ||
230 | exit(EXIT_FAILURE); | ||
231 | } | ||
232 | close(fd); | ||
233 | 228 | ||
234 | /* 9027 (cat) R 6747 9027 6747 34816 9027 ... */ | ||
235 | memset(&comm_ev, 0, sizeof(comm_ev)); | 229 | memset(&comm_ev, 0, sizeof(comm_ev)); |
236 | field = strchr(bf, '('); | 230 | while (!comm_ev.comm[0] || !comm_ev.pid) { |
237 | if (field == NULL) | 231 | if (fgets(bf, sizeof(bf), fp) == NULL) |
238 | goto out_failure; | 232 | goto out_failure; |
239 | sep = strchr(++field, ')'); | 233 | |
240 | if (sep == NULL) | 234 | if (memcmp(bf, "Name:", 5) == 0) { |
241 | goto out_failure; | 235 | char *name = bf + 5; |
242 | size = sep - field; | 236 | while (*name && isspace(*name)) |
243 | memcpy(comm_ev.comm, field, size++); | 237 | ++name; |
244 | 238 | size = strlen(name) - 1; | |
245 | comm_ev.pid = pid; | 239 | memcpy(comm_ev.comm, name, size++); |
240 | } else if (memcmp(bf, "Tgid:", 5) == 0) { | ||
241 | char *tgids = bf + 5; | ||
242 | while (*tgids && isspace(*tgids)) | ||
243 | ++tgids; | ||
244 | tgid = comm_ev.pid = atoi(tgids); | ||
245 | } | ||
246 | } | ||
247 | |||
246 | comm_ev.header.type = PERF_EVENT_COMM; | 248 | comm_ev.header.type = PERF_EVENT_COMM; |
247 | size = ALIGN(size, sizeof(u64)); | 249 | size = ALIGN(size, sizeof(u64)); |
248 | comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); | 250 | comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); |
@@ -251,7 +253,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full) | |||
251 | comm_ev.tid = pid; | 253 | comm_ev.tid = pid; |
252 | 254 | ||
253 | write_output(&comm_ev, comm_ev.header.size); | 255 | write_output(&comm_ev, comm_ev.header.size); |
254 | return; | 256 | goto out_fclose; |
255 | } | 257 | } |
256 | 258 | ||
257 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 259 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); |
@@ -268,7 +270,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full) | |||
268 | write_output(&comm_ev, comm_ev.header.size); | 270 | write_output(&comm_ev, comm_ev.header.size); |
269 | } | 271 | } |
270 | closedir(tasks); | 272 | closedir(tasks); |
271 | return; | 273 | |
274 | out_fclose: | ||
275 | fclose(fp); | ||
276 | return tgid; | ||
272 | 277 | ||
273 | out_failure: | 278 | out_failure: |
274 | fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", | 279 | fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", |
@@ -276,7 +281,7 @@ out_failure: | |||
276 | exit(EXIT_FAILURE); | 281 | exit(EXIT_FAILURE); |
277 | } | 282 | } |
278 | 283 | ||
279 | static void pid_synthesize_mmap_samples(pid_t pid) | 284 | static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid) |
280 | { | 285 | { |
281 | char filename[PATH_MAX]; | 286 | char filename[PATH_MAX]; |
282 | FILE *fp; | 287 | FILE *fp; |
@@ -328,7 +333,7 @@ static void pid_synthesize_mmap_samples(pid_t pid) | |||
328 | mmap_ev.len -= mmap_ev.start; | 333 | mmap_ev.len -= mmap_ev.start; |
329 | mmap_ev.header.size = (sizeof(mmap_ev) - | 334 | mmap_ev.header.size = (sizeof(mmap_ev) - |
330 | (sizeof(mmap_ev.filename) - size)); | 335 | (sizeof(mmap_ev.filename) - size)); |
331 | mmap_ev.pid = pid; | 336 | mmap_ev.pid = tgid; |
332 | mmap_ev.tid = pid; | 337 | mmap_ev.tid = pid; |
333 | 338 | ||
334 | write_output(&mmap_ev, mmap_ev.header.size); | 339 | write_output(&mmap_ev, mmap_ev.header.size); |
@@ -347,14 +352,14 @@ static void synthesize_all(void) | |||
347 | 352 | ||
348 | while (!readdir_r(proc, &dirent, &next) && next) { | 353 | while (!readdir_r(proc, &dirent, &next) && next) { |
349 | char *end; | 354 | char *end; |
350 | pid_t pid; | 355 | pid_t pid, tgid; |
351 | 356 | ||
352 | pid = strtol(dirent.d_name, &end, 10); | 357 | pid = strtol(dirent.d_name, &end, 10); |
353 | if (*end) /* only interested in proper numerical dirents */ | 358 | if (*end) /* only interested in proper numerical dirents */ |
354 | continue; | 359 | continue; |
355 | 360 | ||
356 | pid_synthesize_comm_event(pid, 1); | 361 | tgid = pid_synthesize_comm_event(pid, 1); |
357 | pid_synthesize_mmap_samples(pid); | 362 | pid_synthesize_mmap_samples(pid, tgid); |
358 | } | 363 | } |
359 | 364 | ||
360 | closedir(proc); | 365 | closedir(proc); |
@@ -567,8 +572,8 @@ static int __cmd_record(int argc, const char **argv) | |||
567 | perf_header__write(header, output); | 572 | perf_header__write(header, output); |
568 | 573 | ||
569 | if (!system_wide) { | 574 | if (!system_wide) { |
570 | pid_synthesize_comm_event(pid, 0); | 575 | pid_t tgid = pid_synthesize_comm_event(pid, 0); |
571 | pid_synthesize_mmap_samples(pid); | 576 | pid_synthesize_mmap_samples(pid, tgid); |
572 | } else | 577 | } else |
573 | synthesize_all(); | 578 | synthesize_all(); |
574 | 579 | ||