diff options
| author | David Ahern <dsahern@gmail.com> | 2011-12-22 13:30:02 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-12-23 13:33:57 -0500 |
| commit | f5faf726184a6a5ca1735f610cb97e509fce33e2 (patch) | |
| tree | e69aaefb0316df7059f325cadcceace59f913581 /tools | |
| parent | defd8d38773cf9e01c69a903d04d5895b78ee74f (diff) | |
perf tools: Look up thread names for system wide profiling
This handles multithreaded processes with named threads when doing
system wide profiling: the comm for each thread is looked up allowing
them to be different from the thread group leader.
v2:
- fixed sizeof arg to perf_event__get_comm_tgid
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1324578603-12762-3-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <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 | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index a5787260181a..73ddaf06b8e7 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -43,37 +43,27 @@ static struct perf_sample synth_sample = { | |||
| 43 | .period = 1, | 43 | .period = 1, |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | 46 | static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) |
| 47 | union perf_event *event, pid_t pid, | ||
| 48 | int full, perf_event__handler_t process, | ||
| 49 | struct machine *machine) | ||
| 50 | { | 47 | { |
| 51 | char filename[PATH_MAX]; | 48 | char filename[PATH_MAX]; |
| 52 | char bf[BUFSIZ]; | 49 | char bf[BUFSIZ]; |
| 53 | FILE *fp; | 50 | FILE *fp; |
| 54 | size_t size = 0; | 51 | size_t size = 0; |
| 55 | DIR *tasks; | 52 | pid_t tgid = -1; |
| 56 | struct dirent dirent, *next; | ||
| 57 | pid_t tgid = 0; | ||
| 58 | 53 | ||
| 59 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | 54 | snprintf(filename, sizeof(filename), "/proc/%d/status", pid); |
| 60 | 55 | ||
| 61 | fp = fopen(filename, "r"); | 56 | fp = fopen(filename, "r"); |
| 62 | if (fp == NULL) { | 57 | if (fp == NULL) { |
| 63 | out_race: | ||
| 64 | /* | ||
| 65 | * We raced with a task exiting - just return: | ||
| 66 | */ | ||
| 67 | pr_debug("couldn't open %s\n", filename); | 58 | pr_debug("couldn't open %s\n", filename); |
| 68 | return 0; | 59 | return 0; |
| 69 | } | 60 | } |
| 70 | 61 | ||
| 71 | memset(&event->comm, 0, sizeof(event->comm)); | 62 | while (!comm[0] || (tgid < 0)) { |
| 72 | |||
| 73 | while (!event->comm.comm[0] || !event->comm.pid) { | ||
| 74 | if (fgets(bf, sizeof(bf), fp) == NULL) { | 63 | if (fgets(bf, sizeof(bf), fp) == NULL) { |
| 75 | pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); | 64 | pr_warning("couldn't get COMM and pgid, malformed %s\n", |
| 76 | goto out; | 65 | filename); |
| 66 | break; | ||
| 77 | } | 67 | } |
| 78 | 68 | ||
| 79 | if (memcmp(bf, "Name:", 5) == 0) { | 69 | if (memcmp(bf, "Name:", 5) == 0) { |
| @@ -81,16 +71,46 @@ out_race: | |||
| 81 | while (*name && isspace(*name)) | 71 | while (*name && isspace(*name)) |
| 82 | ++name; | 72 | ++name; |
| 83 | size = strlen(name) - 1; | 73 | size = strlen(name) - 1; |
| 84 | memcpy(event->comm.comm, name, size++); | 74 | if (size >= len) |
| 75 | size = len - 1; | ||
| 76 | memcpy(comm, name, size); | ||
| 77 | |||
| 85 | } else if (memcmp(bf, "Tgid:", 5) == 0) { | 78 | } else if (memcmp(bf, "Tgid:", 5) == 0) { |
| 86 | char *tgids = bf + 5; | 79 | char *tgids = bf + 5; |
| 87 | while (*tgids && isspace(*tgids)) | 80 | while (*tgids && isspace(*tgids)) |
| 88 | ++tgids; | 81 | ++tgids; |
| 89 | tgid = event->comm.pid = atoi(tgids); | 82 | tgid = atoi(tgids); |
| 90 | } | 83 | } |
| 91 | } | 84 | } |
| 92 | 85 | ||
| 86 | fclose(fp); | ||
| 87 | |||
| 88 | return tgid; | ||
| 89 | } | ||
| 90 | |||
| 91 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | ||
| 92 | union perf_event *event, pid_t pid, | ||
| 93 | int full, | ||
| 94 | perf_event__handler_t process, | ||
| 95 | struct machine *machine) | ||
| 96 | { | ||
| 97 | char filename[PATH_MAX]; | ||
| 98 | size_t size; | ||
| 99 | DIR *tasks; | ||
| 100 | struct dirent dirent, *next; | ||
| 101 | pid_t tgid; | ||
| 102 | |||
| 103 | memset(&event->comm, 0, sizeof(event->comm)); | ||
| 104 | |||
| 105 | tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | ||
| 106 | sizeof(event->comm.comm)); | ||
| 107 | if (tgid < 0) | ||
| 108 | goto out; | ||
| 109 | |||
| 110 | event->comm.pid = tgid; | ||
| 93 | event->comm.header.type = PERF_RECORD_COMM; | 111 | event->comm.header.type = PERF_RECORD_COMM; |
| 112 | |||
| 113 | size = strlen(event->comm.comm) + 1; | ||
| 94 | size = ALIGN(size, sizeof(u64)); | 114 | size = ALIGN(size, sizeof(u64)); |
| 95 | memset(event->comm.comm + size, 0, machine->id_hdr_size); | 115 | memset(event->comm.comm + size, 0, machine->id_hdr_size); |
| 96 | event->comm.header.size = (sizeof(event->comm) - | 116 | event->comm.header.size = (sizeof(event->comm) - |
| @@ -106,8 +126,10 @@ out_race: | |||
| 106 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 126 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); |
| 107 | 127 | ||
| 108 | tasks = opendir(filename); | 128 | tasks = opendir(filename); |
| 109 | if (tasks == NULL) | 129 | if (tasks == NULL) { |
| 110 | goto out_race; | 130 | pr_debug("couldn't open %s\n", filename); |
| 131 | return 0; | ||
| 132 | } | ||
| 111 | 133 | ||
| 112 | while (!readdir_r(tasks, &dirent, &next) && next) { | 134 | while (!readdir_r(tasks, &dirent, &next) && next) { |
| 113 | char *end; | 135 | char *end; |
| @@ -115,6 +137,17 @@ out_race: | |||
| 115 | if (*end) | 137 | if (*end) |
| 116 | continue; | 138 | continue; |
| 117 | 139 | ||
| 140 | /* already have tgid; jut want to update the comm */ | ||
| 141 | (void) perf_event__get_comm_tgid(pid, event->comm.comm, | ||
| 142 | sizeof(event->comm.comm)); | ||
| 143 | |||
| 144 | size = strlen(event->comm.comm) + 1; | ||
| 145 | size = ALIGN(size, sizeof(u64)); | ||
| 146 | memset(event->comm.comm + size, 0, machine->id_hdr_size); | ||
| 147 | event->comm.header.size = (sizeof(event->comm) - | ||
| 148 | (sizeof(event->comm.comm) - size) + | ||
| 149 | machine->id_hdr_size); | ||
| 150 | |||
| 118 | event->comm.tid = pid; | 151 | event->comm.tid = pid; |
| 119 | 152 | ||
| 120 | process(tool, event, &synth_sample, machine); | 153 | process(tool, event, &synth_sample, machine); |
| @@ -122,8 +155,6 @@ out_race: | |||
| 122 | 155 | ||
| 123 | closedir(tasks); | 156 | closedir(tasks); |
| 124 | out: | 157 | out: |
| 125 | fclose(fp); | ||
| 126 | |||
| 127 | return tgid; | 158 | return tgid; |
| 128 | } | 159 | } |
| 129 | 160 | ||
