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>
This commit is contained in:
		
					parent
					
						
							
								fb2baceb5a
							
						
					
				
			
			
				commit
				
					
						defd8d3877
					
				
			
		
					 1 changed files with 32 additions and 5 deletions
				
			
		| 
						 | 
					@ -261,11 +261,12 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __event__synthesize_thread(union perf_event *comm_event,
 | 
					static int __event__synthesize_thread(union perf_event *comm_event,
 | 
				
			||||||
				      union perf_event *mmap_event,
 | 
									      union perf_event *mmap_event,
 | 
				
			||||||
				      pid_t pid, perf_event__handler_t process,
 | 
									      pid_t pid, int full,
 | 
				
			||||||
 | 
										  perf_event__handler_t process,
 | 
				
			||||||
				      struct perf_tool *tool,
 | 
									      struct perf_tool *tool,
 | 
				
			||||||
				      struct machine *machine)
 | 
									      struct machine *machine)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1,
 | 
						pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
 | 
				
			||||||
						 process, machine);
 | 
											 process, machine);
 | 
				
			||||||
	if (tgid == -1)
 | 
						if (tgid == -1)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -279,7 +280,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 | 
				
			||||||
				      struct machine *machine)
 | 
									      struct machine *machine)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	union perf_event *comm_event, *mmap_event;
 | 
						union perf_event *comm_event, *mmap_event;
 | 
				
			||||||
	int err = -1, thread;
 | 
						int err = -1, thread, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 | 
						comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 | 
				
			||||||
	if (comm_event == NULL)
 | 
						if (comm_event == NULL)
 | 
				
			||||||
| 
						 | 
					@ -292,11 +293,37 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 | 
				
			||||||
	err = 0;
 | 
						err = 0;
 | 
				
			||||||
	for (thread = 0; thread < threads->nr; ++thread) {
 | 
						for (thread = 0; thread < threads->nr; ++thread) {
 | 
				
			||||||
		if (__event__synthesize_thread(comm_event, mmap_event,
 | 
							if (__event__synthesize_thread(comm_event, mmap_event,
 | 
				
			||||||
					       threads->map[thread],
 | 
										       threads->map[thread], 0,
 | 
				
			||||||
					       process, tool, machine)) {
 | 
										       process, tool, machine)) {
 | 
				
			||||||
			err = -1;
 | 
								err = -1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * comm.pid is set to thread group id by
 | 
				
			||||||
 | 
							 * perf_event__synthesize_comm
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if ((int) comm_event->comm.pid != threads->map[thread]) {
 | 
				
			||||||
 | 
								bool need_leader = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* is thread group leader in thread_map? */
 | 
				
			||||||
 | 
								for (j = 0; j < threads->nr; ++j) {
 | 
				
			||||||
 | 
									if ((int) comm_event->comm.pid == threads->map[j]) {
 | 
				
			||||||
 | 
										need_leader = false;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* if not, generate events for it */
 | 
				
			||||||
 | 
								if (need_leader &&
 | 
				
			||||||
 | 
								    __event__synthesize_thread(comm_event,
 | 
				
			||||||
 | 
											      mmap_event,
 | 
				
			||||||
 | 
											      comm_event->comm.pid, 0,
 | 
				
			||||||
 | 
											      process, tool, machine)) {
 | 
				
			||||||
 | 
									err = -1;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free(mmap_event);
 | 
						free(mmap_event);
 | 
				
			||||||
out_free_comm:
 | 
					out_free_comm:
 | 
				
			||||||
| 
						 | 
					@ -333,7 +360,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
 | 
				
			||||||
		if (*end) /* only interested in proper numerical dirents */
 | 
							if (*end) /* only interested in proper numerical dirents */
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		__event__synthesize_thread(comm_event, mmap_event, pid,
 | 
							__event__synthesize_thread(comm_event, mmap_event, pid, 1,
 | 
				
			||||||
					   process, tool, machine);
 | 
										   process, tool, machine);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue