aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2014-07-16 04:07:13 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-07-17 09:31:02 -0400
commit29ce36121e6738012aaf00d983d25260627f2b0d (patch)
tree1f76cbf7b31b8439fa1a27b05314aad3450261b8 /tools/perf
parent2afd2bcfc3a026d6e4c2184bf41ccd74eb05758b (diff)
perf machine: Fix map groups of threads with unknown pids
Events like sched_switch do not provide a pid (tgid) which can result in threads with an unknown pid. If the pid is later discovered, join the map groups. Note the thread's map groups should be empty because they are populated by MMAP events which do provide the pid and tid. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1405498033-23817-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/machine.c57
-rw-r--r--tools/perf/util/map.c14
-rw-r--r--tools/perf/util/map.h1
3 files changed, 66 insertions, 6 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 5b8087728f28..5484fa4385fc 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -272,6 +272,52 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
272 return; 272 return;
273} 273}
274 274
275static void machine__update_thread_pid(struct machine *machine,
276 struct thread *th, pid_t pid)
277{
278 struct thread *leader;
279
280 if (pid == th->pid_ || pid == -1 || th->pid_ != -1)
281 return;
282
283 th->pid_ = pid;
284
285 if (th->pid_ == th->tid)
286 return;
287
288 leader = machine__findnew_thread(machine, th->pid_, th->pid_);
289 if (!leader)
290 goto out_err;
291
292 if (!leader->mg)
293 leader->mg = map_groups__new();
294
295 if (!leader->mg)
296 goto out_err;
297
298 if (th->mg == leader->mg)
299 return;
300
301 if (th->mg) {
302 /*
303 * Maps are created from MMAP events which provide the pid and
304 * tid. Consequently there never should be any maps on a thread
305 * with an unknown pid. Just print an error if there are.
306 */
307 if (!map_groups__empty(th->mg))
308 pr_err("Discarding thread maps for %d:%d\n",
309 th->pid_, th->tid);
310 map_groups__delete(th->mg);
311 }
312
313 th->mg = map_groups__get(leader->mg);
314
315 return;
316
317out_err:
318 pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid);
319}
320
275static struct thread *__machine__findnew_thread(struct machine *machine, 321static struct thread *__machine__findnew_thread(struct machine *machine,
276 pid_t pid, pid_t tid, 322 pid_t pid, pid_t tid,
277 bool create) 323 bool create)
@@ -285,10 +331,10 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
285 * so most of the time we dont have to look up 331 * so most of the time we dont have to look up
286 * the full rbtree: 332 * the full rbtree:
287 */ 333 */
288 if (machine->last_match && machine->last_match->tid == tid) { 334 th = machine->last_match;
289 if (pid != -1 && pid != machine->last_match->pid_) 335 if (th && th->tid == tid) {
290 machine->last_match->pid_ = pid; 336 machine__update_thread_pid(machine, th, pid);
291 return machine->last_match; 337 return th;
292 } 338 }
293 339
294 while (*p != NULL) { 340 while (*p != NULL) {
@@ -297,8 +343,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
297 343
298 if (th->tid == tid) { 344 if (th->tid == tid) {
299 machine->last_match = th; 345 machine->last_match = th;
300 if (pid != -1 && pid != th->pid_) 346 machine__update_thread_pid(machine, th, pid);
301 th->pid_ = pid;
302 return th; 347 return th;
303 } 348 }
304 349
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 25c571f4cba6..7af14807ee90 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -454,6 +454,20 @@ void map_groups__exit(struct map_groups *mg)
454 } 454 }
455} 455}
456 456
457bool map_groups__empty(struct map_groups *mg)
458{
459 int i;
460
461 for (i = 0; i < MAP__NR_TYPES; ++i) {
462 if (maps__first(&mg->maps[i]))
463 return false;
464 if (!list_empty(&mg->removed_maps[i]))
465 return false;
466 }
467
468 return true;
469}
470
457struct map_groups *map_groups__new(void) 471struct map_groups *map_groups__new(void)
458{ 472{
459 struct map_groups *mg = malloc(sizeof(*mg)); 473 struct map_groups *mg = malloc(sizeof(*mg));
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7758c72522ef..5806a906198b 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -66,6 +66,7 @@ struct map_groups {
66 66
67struct map_groups *map_groups__new(void); 67struct map_groups *map_groups__new(void);
68void map_groups__delete(struct map_groups *mg); 68void map_groups__delete(struct map_groups *mg);
69bool map_groups__empty(struct map_groups *mg);
69 70
70static inline struct map_groups *map_groups__get(struct map_groups *mg) 71static inline struct map_groups *map_groups__get(struct map_groups *mg)
71{ 72{