aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter/builtin-report.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-05-19 08:30:23 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-26 07:52:55 -0400
commitce7e43653b08db094326f378958bc293a68e8e5b (patch)
tree8371422863c531e39c1aa9cd4f20e0ad74728b8a /Documentation/perf_counter/builtin-report.c
parent040e6034124c504d536736ce08e4643e640cd7c2 (diff)
perf_counter: Use rb_tree for symhists and threads in report
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/builtin-report.c')
-rw-r--r--Documentation/perf_counter/builtin-report.c178
1 files changed, 75 insertions, 103 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index f63057fe2cd2..e857201e1e0f 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -479,23 +479,25 @@ static size_t map__fprintf(struct map *self, FILE *fp)
479} 479}
480 480
481struct symhist { 481struct symhist {
482 struct list_head node; 482 struct rb_node rb_node;
483 struct dso *dso; 483 struct dso *dso;
484 struct symbol *sym; 484 struct symbol *sym;
485 uint64_t ip;
485 uint32_t count; 486 uint32_t count;
486 char level; 487 char level;
487}; 488};
488 489
489static struct symhist *symhist__new(struct symbol *sym, struct dso *dso, 490static struct symhist *symhist__new(struct symbol *sym, uint64_t ip,
490 char level) 491 struct dso *dso, char level)
491{ 492{
492 struct symhist *self = malloc(sizeof(*self)); 493 struct symhist *self = malloc(sizeof(*self));
493 494
494 if (self != NULL) { 495 if (self != NULL) {
495 self->sym = sym; 496 self->sym = sym;
497 self->ip = ip;
496 self->dso = dso; 498 self->dso = dso;
497 self->level = level; 499 self->level = level;
498 self->count = 0; 500 self->count = 1;
499 } 501 }
500 502
501 return self; 503 return self;
@@ -506,12 +508,6 @@ static void symhist__delete(struct symhist *self)
506 free(self); 508 free(self);
507} 509}
508 510
509static bool symhist__equal(struct symhist *self, struct symbol *sym,
510 struct dso *dso, char level)
511{
512 return self->level == level && self->sym == sym && self->dso == dso;
513}
514
515static void symhist__inc(struct symhist *self) 511static void symhist__inc(struct symhist *self)
516{ 512{
517 ++self->count; 513 ++self->count;
@@ -519,7 +515,7 @@ static void symhist__inc(struct symhist *self)
519 515
520static size_t symhist__fprintf(struct symhist *self, FILE *fp) 516static size_t symhist__fprintf(struct symhist *self, FILE *fp)
521{ 517{
522 size_t ret = fprintf(fp, "[%c] ", self->level); 518 size_t ret = fprintf(fp, "%#llx [%c] ", (unsigned long long)self->ip, self->level);
523 519
524 if (self->level != '.') 520 if (self->level != '.')
525 ret += fprintf(fp, "%s", self->sym->name); 521 ret += fprintf(fp, "%s", self->sym->name);
@@ -531,9 +527,9 @@ static size_t symhist__fprintf(struct symhist *self, FILE *fp)
531} 527}
532 528
533struct thread { 529struct thread {
534 struct list_head node; 530 struct rb_node rb_node;
535 struct list_head maps; 531 struct list_head maps;
536 struct list_head symhists; 532 struct rb_root symhists;
537 pid_t pid; 533 pid_t pid;
538 char *comm; 534 char *comm;
539}; 535};
@@ -546,47 +542,43 @@ static struct thread *thread__new(pid_t pid)
546 self->pid = pid; 542 self->pid = pid;
547 self->comm = NULL; 543 self->comm = NULL;
548 INIT_LIST_HEAD(&self->maps); 544 INIT_LIST_HEAD(&self->maps);
549 INIT_LIST_HEAD(&self->symhists); 545 self->symhists = RB_ROOT;
550 } 546 }
551 547
552 return self; 548 return self;
553} 549}
554 550
555static void thread__insert_symhist(struct thread *self, 551static int thread__symbol_incnew(struct thread *self, struct symbol *sym,
556 struct symhist *symhist) 552 uint64_t ip, struct dso *dso, char level)
557{
558 list_add_tail(&symhist->node, &self->symhists);
559}
560
561static struct symhist *thread__symhists_find(struct thread *self,
562 struct symbol *sym,
563 struct dso *dso, char level)
564{ 553{
565 struct symhist *pos; 554 struct rb_node **p = &self->symhists.rb_node;
555 struct rb_node *parent = NULL;
556 struct symhist *sh;
566 557
567 list_for_each_entry(pos, &self->symhists, node) 558 while (*p != NULL) {
568 if (symhist__equal(pos, sym, dso, level)) 559 parent = *p;
569 return pos; 560 sh = rb_entry(parent, struct symhist, rb_node);
570 561
571 return NULL; 562 if (sh->sym == sym || ip == sh->ip) {
572} 563 symhist__inc(sh);
564 return 0;
565 }
573 566
574static int thread__symbol_incnew(struct thread *self, struct symbol *sym, 567 /* Handle unresolved symbols too */
575 struct dso *dso, char level) 568 const uint64_t start = !sh->sym ? sh->ip : sh->sym->start;
576{
577 struct symhist *symhist = thread__symhists_find(self, sym, dso, level);
578 569
579 if (symhist == NULL) { 570 if (ip < start)
580 symhist = symhist__new(sym, dso, level); 571 p = &(*p)->rb_left;
581 if (symhist == NULL) 572 else
582 goto out_error; 573 p = &(*p)->rb_right;
583 thread__insert_symhist(self, symhist);
584 } 574 }
585 575
586 symhist__inc(symhist); 576 sh = symhist__new(sym, ip, dso, level);
577 if (sh == NULL)
578 return -ENOMEM;
579 rb_link_node(&sh->rb_node, parent, p);
580 rb_insert_color(&sh->rb_node, &self->symhists);
587 return 0; 581 return 0;
588out_error:
589 return -ENOMEM;
590} 582}
591 583
592static int thread__set_comm(struct thread *self, const char *comm) 584static int thread__set_comm(struct thread *self, const char *comm)
@@ -608,43 +600,44 @@ static size_t thread__maps_fprintf(struct thread *self, FILE *fp)
608 600
609static size_t thread__fprintf(struct thread *self, FILE *fp) 601static size_t thread__fprintf(struct thread *self, FILE *fp)
610{ 602{
611 struct symhist *pos;
612 int ret = fprintf(fp, "thread: %d %s\n", self->pid, self->comm); 603 int ret = fprintf(fp, "thread: %d %s\n", self->pid, self->comm);
604 struct rb_node *nd;
613 605
614 list_for_each_entry(pos, &self->symhists, node) 606 for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) {
607 struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
615 ret += symhist__fprintf(pos, fp); 608 ret += symhist__fprintf(pos, fp);
609 }
616 610
617 return ret; 611 return ret;
618} 612}
619 613
620static LIST_HEAD(threads); 614static struct rb_root threads = RB_ROOT;
621 615
622static void threads__add(struct thread *thread) 616static struct thread *threads__findnew(pid_t pid)
623{
624 list_add_tail(&thread->node, &threads);
625}
626
627static struct thread *threads__find(pid_t pid)
628{ 617{
629 struct thread *pos; 618 struct rb_node **p = &threads.rb_node;
619 struct rb_node *parent = NULL;
620 struct thread *th;
630 621
631 list_for_each_entry(pos, &threads, node) 622 while (*p != NULL) {
632 if (pos->pid == pid) 623 parent = *p;
633 return pos; 624 th = rb_entry(parent, struct thread, rb_node);
634 return NULL;
635}
636 625
637static struct thread *threads__findnew(pid_t pid) 626 if (th->pid == pid)
638{ 627 return th;
639 struct thread *thread = threads__find(pid);
640 628
641 if (thread == NULL) { 629 if (pid < th->pid)
642 thread = thread__new(pid); 630 p = &(*p)->rb_left;
643 if (thread != NULL) 631 else
644 threads__add(thread); 632 p = &(*p)->rb_right;
645 } 633 }
646 634
647 return thread; 635 th = thread__new(pid);
636 if (th != NULL) {
637 rb_link_node(&th->rb_node, parent, p);
638 rb_insert_color(&th->rb_node, &threads);
639 }
640 return th;
648} 641}
649 642
650static void thread__insert_map(struct thread *self, struct map *map) 643static void thread__insert_map(struct thread *self, struct map *map)
@@ -668,44 +661,13 @@ static struct map *thread__find_map(struct thread *self, uint64_t ip)
668 661
669static void threads__fprintf(FILE *fp) 662static void threads__fprintf(FILE *fp)
670{ 663{
671 struct thread *pos; 664 struct rb_node *nd;
672 665 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
673 list_for_each_entry(pos, &threads, node) 666 struct thread *pos = rb_entry(nd, struct thread, rb_node);
674 thread__fprintf(pos, fp); 667 thread__fprintf(pos, fp);
668 }
675} 669}
676 670
677#if 0
678static std::string resolve_user_symbol(int pid, uint64_t ip)
679{
680 std::string sym = "<unknown>";
681
682 maps_t &m = maps[pid];
683 maps_t::const_iterator mi = m.upper_bound(map(ip));
684 if (mi == m.end())
685 return sym;
686
687 ip -= mi->start + mi->pgoff;
688
689 symbols_t &s = dsos[mi->dso].syms;
690 symbols_t::const_iterator si = s.upper_bound(symbol(ip));
691
692 sym = mi->dso + ": <unknown>";
693
694 if (si == s.begin())
695 return sym;
696 si--;
697
698 if (si->start <= ip && ip < si->end)
699 sym = mi->dso + ": " + si->name;
700#if 0
701 else if (si->start <= ip)
702 sym = mi->dso + ": ?" + si->name;
703#endif
704
705 return sym;
706}
707#endif
708
709static void display_help(void) 671static void display_help(void)
710{ 672{
711 printf( 673 printf(
@@ -824,8 +786,11 @@ more:
824 struct dso *dso = NULL; 786 struct dso *dso = NULL;
825 struct thread *thread = threads__findnew(event->ip.pid); 787 struct thread *thread = threads__findnew(event->ip.pid);
826 788
827 if (thread == NULL) 789 if (thread == NULL) {
790 fprintf(stderr, "problem processing %d event, bailing out\n",
791 event->header.type);
828 goto done; 792 goto done;
793 }
829 794
830 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 795 if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
831 show = SHOW_KERNEL; 796 show = SHOW_KERNEL;
@@ -845,8 +810,11 @@ more:
845 if (show & show_mask) { 810 if (show & show_mask) {
846 struct symbol *sym = dso__find_symbol(dso, event->ip.ip); 811 struct symbol *sym = dso__find_symbol(dso, event->ip.ip);
847 812
848 if (thread__symbol_incnew(thread, sym, dso, level)) 813 if (thread__symbol_incnew(thread, sym, event->ip.ip,
814 dso, level)) {
815 fprintf(stderr, "problem incrementing symbol count, bailing out\n");
849 goto done; 816 goto done;
817 }
850 } 818 }
851 total++; 819 total++;
852 } else switch (event->header.type) { 820 } else switch (event->header.type) {
@@ -854,8 +822,10 @@ more:
854 struct thread *thread = threads__findnew(event->mmap.pid); 822 struct thread *thread = threads__findnew(event->mmap.pid);
855 struct map *map = map__new(&event->mmap); 823 struct map *map = map__new(&event->mmap);
856 824
857 if (thread == NULL || map == NULL ) 825 if (thread == NULL || map == NULL) {
826 fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
858 goto done; 827 goto done;
828 }
859 thread__insert_map(thread, map); 829 thread__insert_map(thread, map);
860 break; 830 break;
861 } 831 }
@@ -863,8 +833,10 @@ more:
863 struct thread *thread = threads__findnew(event->comm.pid); 833 struct thread *thread = threads__findnew(event->comm.pid);
864 834
865 if (thread == NULL || 835 if (thread == NULL ||
866 thread__set_comm(thread, event->comm.comm)) 836 thread__set_comm(thread, event->comm.comm)) {
837 fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
867 goto done; 838 goto done;
839 }
868 break; 840 break;
869 } 841 }
870 } 842 }