Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+32 -73
+22 -15
tools/perf/util/hist.c
··· 313 313 memset(&he->stat, 0, sizeof(he->stat)); 314 314 } 315 315 316 - if (he->ms.map) 317 - he->ms.map->referenced = true; 316 + map__get(he->ms.map); 318 317 319 318 if (he->branch_info) { 320 319 /* ··· 323 324 */ 324 325 he->branch_info = malloc(sizeof(*he->branch_info)); 325 326 if (he->branch_info == NULL) { 327 + map__zput(he->ms.map); 326 328 free(he->stat_acc); 327 329 free(he); 328 330 return NULL; ··· 332 332 memcpy(he->branch_info, template->branch_info, 333 333 sizeof(*he->branch_info)); 334 334 335 - if (he->branch_info->from.map) 336 - he->branch_info->from.map->referenced = true; 337 - if (he->branch_info->to.map) 338 - he->branch_info->to.map->referenced = true; 335 + map__get(he->branch_info->from.map); 336 + map__get(he->branch_info->to.map); 339 337 } 340 338 341 339 if (he->mem_info) { 342 - if (he->mem_info->iaddr.map) 343 - he->mem_info->iaddr.map->referenced = true; 344 - if (he->mem_info->daddr.map) 345 - he->mem_info->daddr.map->referenced = true; 340 + map__get(he->mem_info->iaddr.map); 341 + map__get(he->mem_info->daddr.map); 346 342 } 347 343 348 344 if (symbol_conf.use_callchain) ··· 403 407 * the history counter to increment. 404 408 */ 405 409 if (he->ms.map != entry->ms.map) { 406 - he->ms.map = entry->ms.map; 407 - if (he->ms.map) 408 - he->ms.map->referenced = true; 410 + map__put(he->ms.map); 411 + he->ms.map = map__get(entry->ms.map); 409 412 } 410 413 goto out; 411 414 } ··· 928 933 void hist_entry__delete(struct hist_entry *he) 929 934 { 930 935 thread__zput(he->thread); 931 - zfree(&he->branch_info); 932 - zfree(&he->mem_info); 936 + map__zput(he->ms.map); 937 + 938 + if (he->branch_info) { 939 + map__zput(he->branch_info->from.map); 940 + map__zput(he->branch_info->to.map); 941 + zfree(&he->branch_info); 942 + } 943 + 944 + if (he->mem_info) { 945 + map__zput(he->mem_info->iaddr.map); 946 + map__zput(he->mem_info->daddr.map); 947 + zfree(&he->mem_info); 948 + } 949 + 933 950 zfree(&he->stat_acc); 934 951 free_srcline(he->srcline); 935 952 free_callchain(he->callchain);
+2 -56
tools/perf/util/map.c
··· 137 137 map->unmap_ip = map__unmap_ip; 138 138 RB_CLEAR_NODE(&map->rb_node); 139 139 map->groups = NULL; 140 - map->referenced = false; 141 140 map->erange_warned = false; 142 141 atomic_set(&map->refcnt, 1); 143 142 } ··· 438 439 { 439 440 maps->entries = RB_ROOT; 440 441 pthread_rwlock_init(&maps->lock, NULL); 441 - INIT_LIST_HEAD(&maps->removed_maps); 442 442 } 443 443 444 444 void map_groups__init(struct map_groups *mg, struct machine *machine) ··· 464 466 } 465 467 } 466 468 467 - static void __maps__purge_removed_maps(struct maps *maps) 468 - { 469 - struct map *pos, *n; 470 - 471 - list_for_each_entry_safe(pos, n, &maps->removed_maps, node) { 472 - list_del_init(&pos->node); 473 - map__put(pos); 474 - } 475 - } 476 - 477 469 static void maps__exit(struct maps *maps) 478 470 { 479 471 pthread_rwlock_wrlock(&maps->lock); 480 472 __maps__purge(maps); 481 - __maps__purge_removed_maps(maps); 482 473 pthread_rwlock_unlock(&maps->lock); 483 474 } 484 475 ··· 485 498 486 499 for (i = 0; i < MAP__NR_TYPES; ++i) { 487 500 if (maps__first(&mg->maps[i])) 488 - return false; 489 - if (!list_empty(&mg->maps[i].removed_maps)) 490 501 return false; 491 502 } 492 503 ··· 606 621 return printed += maps__fprintf(&mg->maps[type], fp); 607 622 } 608 623 609 - static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) 624 + size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 610 625 { 611 626 size_t printed = 0, i; 612 627 for (i = 0; i < MAP__NR_TYPES; ++i) 613 628 printed += __map_groups__fprintf_maps(mg, i, fp); 614 629 return printed; 615 - } 616 - 617 - static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, 618 - enum map_type type, FILE *fp) 619 - { 620 - struct map *pos; 621 - size_t printed = 0; 622 - 623 - list_for_each_entry(pos, &mg->maps[type].removed_maps, node) { 624 - printed += fprintf(fp, "Map:"); 625 - printed += map__fprintf(pos, fp); 626 - if (verbose > 1) { 627 - printed += dso__fprintf(pos->dso, type, fp); 628 - printed += fprintf(fp, "--\n"); 629 - } 630 - } 631 - return printed; 632 - } 633 - 634 - static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, 635 - FILE *fp) 636 - { 637 - size_t printed = 0, i; 638 - for (i = 0; i < MAP__NR_TYPES; ++i) 639 - printed += __map_groups__fprintf_removed_maps(mg, i, fp); 640 - return printed; 641 - } 642 - 643 - size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 644 - { 645 - size_t printed = map_groups__fprintf_maps(mg, fp); 646 - printed += fprintf(fp, "Removed maps:\n"); 647 - return printed + map_groups__fprintf_removed_maps(mg, fp); 648 630 } 649 631 650 632 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) ··· 671 719 map__fprintf(after, fp); 672 720 } 673 721 put_map: 674 - /* 675 - * If we have references, just move them to a separate list. 676 - */ 677 - if (pos->referenced) 678 - list_add_tail(&pos->node, &maps->removed_maps); 679 - else 680 - map__put(pos); 722 + map__put(pos); 681 723 682 724 if (err) 683 725 goto out;
+8 -2
tools/perf/util/map.h
··· 34 34 u64 start; 35 35 u64 end; 36 36 u8 /* enum map_type */ type; 37 - bool referenced; 38 37 bool erange_warned; 39 38 u32 priv; 40 39 u32 prot; ··· 62 63 struct maps { 63 64 struct rb_root entries; 64 65 pthread_rwlock_t lock; 65 - struct list_head removed_maps; 66 66 }; 67 67 68 68 struct map_groups { ··· 158 160 } 159 161 160 162 void map__put(struct map *map); 163 + 164 + static inline void __map__zput(struct map **map) 165 + { 166 + map__put(*map); 167 + *map = NULL; 168 + } 169 + 170 + #define map__zput(map) __map__zput(&map) 161 171 162 172 int map__overlap(struct map *l, struct map *r); 163 173 size_t map__fprintf(struct map *map, FILE *fp);