aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-06-15 22:29:51 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-06-16 09:34:38 -0400
commit5c24b67aae72f54c5d2a6898be4bae9726df63bb (patch)
tree14cf53530c0b85b7e1cb5599c62be9a059ab978b
parent35a23ff928b066b00a826d0a9ed9411b8ab479ef (diff)
perf tools: Replace map->referenced & maps->removed_maps with map->refcnt
Use just reference counts, so that when no more hist_entry instances references a map and the thread instance goes away by processing a PERF_RECORD_EXIT, we can delete the maps. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: David Ahern <dsahern@gmail.com> Cc: Don Zickus <dzickus@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-oym7lfhcc7ss6xpz44h7nbxs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/hist.c37
-rw-r--r--tools/perf/util/map.c58
-rw-r--r--tools/perf/util/map.h10
3 files changed, 32 insertions, 73 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f53d017c7c22..6f28d53d4e46 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
313 memset(&he->stat, 0, sizeof(he->stat)); 313 memset(&he->stat, 0, sizeof(he->stat));
314 } 314 }
315 315
316 if (he->ms.map) 316 map__get(he->ms.map);
317 he->ms.map->referenced = true;
318 317
319 if (he->branch_info) { 318 if (he->branch_info) {
320 /* 319 /*
@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
324 */ 323 */
325 he->branch_info = malloc(sizeof(*he->branch_info)); 324 he->branch_info = malloc(sizeof(*he->branch_info));
326 if (he->branch_info == NULL) { 325 if (he->branch_info == NULL) {
326 map__zput(he->ms.map);
327 free(he->stat_acc); 327 free(he->stat_acc);
328 free(he); 328 free(he);
329 return NULL; 329 return NULL;
@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
332 memcpy(he->branch_info, template->branch_info, 332 memcpy(he->branch_info, template->branch_info,
333 sizeof(*he->branch_info)); 333 sizeof(*he->branch_info));
334 334
335 if (he->branch_info->from.map) 335 map__get(he->branch_info->from.map);
336 he->branch_info->from.map->referenced = true; 336 map__get(he->branch_info->to.map);
337 if (he->branch_info->to.map)
338 he->branch_info->to.map->referenced = true;
339 } 337 }
340 338
341 if (he->mem_info) { 339 if (he->mem_info) {
342 if (he->mem_info->iaddr.map) 340 map__get(he->mem_info->iaddr.map);
343 he->mem_info->iaddr.map->referenced = true; 341 map__get(he->mem_info->daddr.map);
344 if (he->mem_info->daddr.map)
345 he->mem_info->daddr.map->referenced = true;
346 } 342 }
347 343
348 if (symbol_conf.use_callchain) 344 if (symbol_conf.use_callchain)
@@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
407 * the history counter to increment. 403 * the history counter to increment.
408 */ 404 */
409 if (he->ms.map != entry->ms.map) { 405 if (he->ms.map != entry->ms.map) {
410 he->ms.map = entry->ms.map; 406 map__put(he->ms.map);
411 if (he->ms.map) 407 he->ms.map = map__get(entry->ms.map);
412 he->ms.map->referenced = true;
413 } 408 }
414 goto out; 409 goto out;
415 } 410 }
@@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
933void hist_entry__delete(struct hist_entry *he) 928void hist_entry__delete(struct hist_entry *he)
934{ 929{
935 thread__zput(he->thread); 930 thread__zput(he->thread);
936 zfree(&he->branch_info); 931 map__zput(he->ms.map);
937 zfree(&he->mem_info); 932
933 if (he->branch_info) {
934 map__zput(he->branch_info->from.map);
935 map__zput(he->branch_info->to.map);
936 zfree(&he->branch_info);
937 }
938
939 if (he->mem_info) {
940 map__zput(he->mem_info->iaddr.map);
941 map__zput(he->mem_info->daddr.map);
942 zfree(&he->mem_info);
943 }
944
938 zfree(&he->stat_acc); 945 zfree(&he->stat_acc);
939 free_srcline(he->srcline); 946 free_srcline(he->srcline);
940 free_callchain(he->callchain); 947 free_callchain(he->callchain);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 1241ab989cf5..b5a5e9c02437 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -137,7 +137,6 @@ void map__init(struct map *map, enum map_type type,
137 map->unmap_ip = map__unmap_ip; 137 map->unmap_ip = map__unmap_ip;
138 RB_CLEAR_NODE(&map->rb_node); 138 RB_CLEAR_NODE(&map->rb_node);
139 map->groups = NULL; 139 map->groups = NULL;
140 map->referenced = false;
141 map->erange_warned = false; 140 map->erange_warned = false;
142 atomic_set(&map->refcnt, 1); 141 atomic_set(&map->refcnt, 1);
143} 142}
@@ -439,7 +438,6 @@ static void maps__init(struct maps *maps)
439{ 438{
440 maps->entries = RB_ROOT; 439 maps->entries = RB_ROOT;
441 pthread_rwlock_init(&maps->lock, NULL); 440 pthread_rwlock_init(&maps->lock, NULL);
442 INIT_LIST_HEAD(&maps->removed_maps);
443} 441}
444 442
445void map_groups__init(struct map_groups *mg, struct machine *machine) 443void map_groups__init(struct map_groups *mg, struct machine *machine)
@@ -466,21 +464,10 @@ static void __maps__purge(struct maps *maps)
466 } 464 }
467} 465}
468 466
469static void __maps__purge_removed_maps(struct maps *maps)
470{
471 struct map *pos, *n;
472
473 list_for_each_entry_safe(pos, n, &maps->removed_maps, node) {
474 list_del_init(&pos->node);
475 map__put(pos);
476 }
477}
478
479static void maps__exit(struct maps *maps) 467static void maps__exit(struct maps *maps)
480{ 468{
481 pthread_rwlock_wrlock(&maps->lock); 469 pthread_rwlock_wrlock(&maps->lock);
482 __maps__purge(maps); 470 __maps__purge(maps);
483 __maps__purge_removed_maps(maps);
484 pthread_rwlock_unlock(&maps->lock); 471 pthread_rwlock_unlock(&maps->lock);
485} 472}
486 473
@@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg)
499 for (i = 0; i < MAP__NR_TYPES; ++i) { 486 for (i = 0; i < MAP__NR_TYPES; ++i) {
500 if (maps__first(&mg->maps[i])) 487 if (maps__first(&mg->maps[i]))
501 return false; 488 return false;
502 if (!list_empty(&mg->maps[i].removed_maps))
503 return false;
504 } 489 }
505 490
506 return true; 491 return true;
@@ -621,7 +606,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
621 return printed += maps__fprintf(&mg->maps[type], fp); 606 return printed += maps__fprintf(&mg->maps[type], fp);
622} 607}
623 608
624static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) 609size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
625{ 610{
626 size_t printed = 0, i; 611 size_t printed = 0, i;
627 for (i = 0; i < MAP__NR_TYPES; ++i) 612 for (i = 0; i < MAP__NR_TYPES; ++i)
@@ -629,39 +614,6 @@ static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp)
629 return printed; 614 return printed;
630} 615}
631 616
632static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg,
633 enum map_type type, FILE *fp)
634{
635 struct map *pos;
636 size_t printed = 0;
637
638 list_for_each_entry(pos, &mg->maps[type].removed_maps, node) {
639 printed += fprintf(fp, "Map:");
640 printed += map__fprintf(pos, fp);
641 if (verbose > 1) {
642 printed += dso__fprintf(pos->dso, type, fp);
643 printed += fprintf(fp, "--\n");
644 }
645 }
646 return printed;
647}
648
649static size_t map_groups__fprintf_removed_maps(struct map_groups *mg,
650 FILE *fp)
651{
652 size_t printed = 0, i;
653 for (i = 0; i < MAP__NR_TYPES; ++i)
654 printed += __map_groups__fprintf_removed_maps(mg, i, fp);
655 return printed;
656}
657
658size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
659{
660 size_t printed = map_groups__fprintf_maps(mg, fp);
661 printed += fprintf(fp, "Removed maps:\n");
662 return printed + map_groups__fprintf_removed_maps(mg, fp);
663}
664
665static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 617static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
666{ 618{
667 struct rb_root *root; 619 struct rb_root *root;
@@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
719 map__fprintf(after, fp); 671 map__fprintf(after, fp);
720 } 672 }
721put_map: 673put_map:
722 /* 674 map__put(pos);
723 * If we have references, just move them to a separate list.
724 */
725 if (pos->referenced)
726 list_add_tail(&pos->node, &maps->removed_maps);
727 else
728 map__put(pos);
729 675
730 if (err) 676 if (err)
731 goto out; 677 goto out;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index b8df09d94aca..d73e687b224e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -34,7 +34,6 @@ struct map {
34 u64 start; 34 u64 start;
35 u64 end; 35 u64 end;
36 u8 /* enum map_type */ type; 36 u8 /* enum map_type */ type;
37 bool referenced;
38 bool erange_warned; 37 bool erange_warned;
39 u32 priv; 38 u32 priv;
40 u32 prot; 39 u32 prot;
@@ -63,7 +62,6 @@ struct kmap {
63struct maps { 62struct maps {
64 struct rb_root entries; 63 struct rb_root entries;
65 pthread_rwlock_t lock; 64 pthread_rwlock_t lock;
66 struct list_head removed_maps;
67}; 65};
68 66
69struct map_groups { 67struct map_groups {
@@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map)
161 159
162void map__put(struct map *map); 160void map__put(struct map *map);
163 161
162static inline void __map__zput(struct map **map)
163{
164 map__put(*map);
165 *map = NULL;
166}
167
168#define map__zput(map) __map__zput(&map)
169
164int map__overlap(struct map *l, struct map *r); 170int map__overlap(struct map *l, struct map *r);
165size_t map__fprintf(struct map *map, FILE *fp); 171size_t map__fprintf(struct map *map, FILE *fp);
166size_t map__fprintf_dsoname(struct map *map, FILE *fp); 172size_t map__fprintf_dsoname(struct map *map, FILE *fp);