aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2011-12-22 13:30:01 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-12-23 13:10:40 -0500
commitdefd8d38773cf9e01c69a903d04d5895b78ee74f (patch)
tree1b6bba5c215fc09e499d7e364dbc1f32479dea23 /tools/perf/util/event.c
parentfb2baceb5a64990163e93b77ee205d0173202ee6 (diff)
perf tools: Fix comm for processes with named threads
perf does not properly handle monitoring of processes with named threads. For example: $ ps -C myapp -L PID LWP TTY TIME CMD 25118 25118 ? 00:00:00 myapp 25118 25119 ? 00:00:00 myapp:worker perf record -e cs -c 1 -fo /tmp/perf.data -p 25118 -- sleep 10 perf report --stdio -i /tmp/perf.data 100.00% myapp:worker [kernel.kallsyms] [k] perf_event_task_sched_out The process name is set to the name of the last thread it finds for the process. The Problem: perf-top and perf-record both create a thread_map of threads to be monitored. That map is used in perf_event__synthesize_thread_map which loops over the entries in thread_map and calls __event__synthesize_thread to generate COMM and MMAP events. __event__synthesize_thread calls perf_event__synthesize_comm which opens /proc/pid/status, reads the name of the task and its thread group id. That's all fine. The problem is that it then reads /proc/pid/task and generates COMM events for each task it finds - but using the name found in /proc/pid/status where pid is the thread of interest. The end result (looping over thread_map + synthesizing comm events for each thread each time) means the name of the last thread processed sets the name for all threads in the process - which is not good for multithreaded processes with named threads. The Fix: perf_event__synthesize_comm has an input argument (full) that decides whether to process task entries for each pid it is passed. It currently never set to 0 (perf_event__synthesize_comm has a single caller and it always passes the value 1). Let's fix that. Add the full input argument to __event__synthesize_thread which passes it to perf_event__synthesize_comm. For thread/process monitoring set full to 0 which means COMM and MMAP events are only generated for the pid passed to it. For system wide monitoring set full to 1 so that COMM events are generated for all threads in a process. 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-2-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/util/event.c')
-rw-r--r--tools/perf/util/event.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b7c7f39a8f6d..a5787260181a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -261,11 +261,12 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
261 261
262static int __event__synthesize_thread(union perf_event *comm_event, 262static int __event__synthesize_thread(union perf_event *comm_event,
263 union perf_event *mmap_event, 263 union perf_event *mmap_event,
264 pid_t pid, perf_event__handler_t process, 264 pid_t pid, int full,
265 perf_event__handler_t process,
265 struct perf_tool *tool, 266 struct perf_tool *tool,
266 struct machine *machine) 267 struct machine *machine)
267{ 268{
268 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1, 269 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
269 process, machine); 270 process, machine);
270 if (tgid == -1) 271 if (tgid == -1)
271 return -1; 272 return -1;
@@ -279,7 +280,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
279 struct machine *machine) 280 struct machine *machine)
280{ 281{
281 union perf_event *comm_event, *mmap_event; 282 union perf_event *comm_event, *mmap_event;
282 int err = -1, thread; 283 int err = -1, thread, j;
283 284
284 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 285 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
285 if (comm_event == NULL) 286 if (comm_event == NULL)
@@ -292,11 +293,37 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
292 err = 0; 293 err = 0;
293 for (thread = 0; thread < threads->nr; ++thread) { 294 for (thread = 0; thread < threads->nr; ++thread) {
294 if (__event__synthesize_thread(comm_event, mmap_event, 295 if (__event__synthesize_thread(comm_event, mmap_event,
295 threads->map[thread], 296 threads->map[thread], 0,
296 process, tool, machine)) { 297 process, tool, machine)) {
297 err = -1; 298 err = -1;
298 break; 299 break;
299 } 300 }
301
302 /*
303 * comm.pid is set to thread group id by
304 * perf_event__synthesize_comm
305 */
306 if ((int) comm_event->comm.pid != threads->map[thread]) {
307 bool need_leader = true;
308
309 /* is thread group leader in thread_map? */
310 for (j = 0; j < threads->nr; ++j) {
311 if ((int) comm_event->comm.pid == threads->map[j]) {
312 need_leader = false;
313 break;
314 }
315 }
316
317 /* if not, generate events for it */
318 if (need_leader &&
319 __event__synthesize_thread(comm_event,
320 mmap_event,
321 comm_event->comm.pid, 0,
322 process, tool, machine)) {
323 err = -1;
324 break;
325 }
326 }
300 } 327 }
301 free(mmap_event); 328 free(mmap_event);
302out_free_comm: 329out_free_comm:
@@ -333,7 +360,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
333 if (*end) /* only interested in proper numerical dirents */ 360 if (*end) /* only interested in proper numerical dirents */
334 continue; 361 continue;
335 362
336 __event__synthesize_thread(comm_event, mmap_event, pid, 363 __event__synthesize_thread(comm_event, mmap_event, pid, 1,
337 process, tool, machine); 364 process, tool, machine);
338 } 365 }
339 366