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/perf | |
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/perf')
-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 | ||