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 | ||
