perf annotate: Move locking to struct annotation

Since we'll need it when implementing the live annotate TUI browser.

This also simplifies things a bit by having the list head for the source
code to be in the dynamicly allocated part of struct annotation, that
way we don't have to pass it around, it can be found from the struct
symbol that is passed everywhere.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 6db4351..c777bda 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,25 +14,39 @@
 #include "symbol.h"
 #include "debug.h"
 #include "annotate.h"
+#include <pthread.h>
+
+int symbol__annotate_init(struct map *map __used, struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	pthread_mutex_init(&notes->lock, NULL);
+	return 0;
+}
 
 int symbol__alloc_hist(struct symbol *sym, int nevents)
 {
 	struct annotation *notes = symbol__annotation(sym);
-
-	notes->sizeof_sym_hist = (sizeof(*notes->histograms) +
+	size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
 				  (sym->end - sym->start) * sizeof(u64));
-	notes->histograms = calloc(nevents, notes->sizeof_sym_hist);
-	notes->nr_histograms = nevents;
-	return notes->histograms == NULL ? -1 : 0;
+
+	notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
+	if (notes->src == NULL)
+		return -1;
+	notes->src->sizeof_sym_hist = sizeof_sym_hist;
+	notes->src->nr_histograms   = nevents;
+	INIT_LIST_HEAD(&notes->src->source);
+	return 0;
 }
 
 void symbol__annotate_zero_histograms(struct symbol *sym)
 {
 	struct annotation *notes = symbol__annotation(sym);
 
-	if (notes->histograms != NULL)
-		memset(notes->histograms, 0,
-		       notes->nr_histograms * notes->sizeof_sym_hist);
+	pthread_mutex_lock(&notes->lock);
+	if (notes->src != NULL)
+		memset(notes->src->histograms, 0,
+		       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
+	pthread_mutex_unlock(&notes->lock);
 }
 
 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
@@ -43,7 +57,7 @@
 	struct sym_hist *h;
 
 	notes = symbol__annotation(sym);
-	if (notes->histograms == NULL)
+	if (notes->src == NULL)
 		return -ENOMEM;
 
 	pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
@@ -95,8 +109,7 @@
 	return NULL;
 }
 
-static int objdump_line__print(struct objdump_line *oline,
-			       struct list_head *head, struct symbol *sym,
+static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
 			       int evidx, u64 len, int min_pcnt,
 			       int printed, int max_lines)
 {
@@ -109,10 +122,12 @@
 		double percent = 0.0;
 		const char *color;
 		struct annotation *notes = symbol__annotation(sym);
-		struct source_line *src_line = notes->src_line;
+		struct source_line *src_line = notes->src->lines;
 		struct sym_hist *h = annotation__histogram(notes, evidx);
 		s64 offset = oline->offset;
-		struct objdump_line *next = objdump__get_next_ip_line(head, oline);
+		struct objdump_line *next;
+
+		next = objdump__get_next_ip_line(&notes->src->source, oline);
 
 		while (offset < (s64)len &&
 		       (next == NULL || offset < next->offset)) {
@@ -166,9 +181,10 @@
 	return 0;
 }
 
-static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file,
-				      struct list_head *head, size_t privsize)
+static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
+				      FILE *file, size_t privsize)
 {
+	struct annotation *notes = symbol__annotation(sym);
 	struct objdump_line *objdump_line;
 	char *line = NULL, *tmp, *tmp2, *c;
 	size_t line_len;
@@ -222,13 +238,12 @@
 		free(line);
 		return -1;
 	}
-	objdump__add_line(head, objdump_line);
+	objdump__add_line(&notes->src->source, objdump_line);
 
 	return 0;
 }
 
-int symbol__annotate(struct symbol *sym, struct map *map,
-		     struct list_head *head, size_t privsize)
+int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
 {
 	struct dso *dso = map->dso;
 	char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -297,7 +312,7 @@
 		goto out_free_filename;
 
 	while (!feof(file))
-		if (symbol__parse_objdump_line(sym, map, file, head, privsize) < 0)
+		if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
 			break;
 
 	pclose(file);
@@ -330,14 +345,14 @@
 static void symbol__free_source_line(struct symbol *sym, int len)
 {
 	struct annotation *notes = symbol__annotation(sym);
-	struct source_line *src_line = notes->src_line;
+	struct source_line *src_line = notes->src->lines;
 	int i;
 
 	for (i = 0; i < len; i++)
 		free(src_line[i].path);
 
 	free(src_line);
-	notes->src_line = NULL;
+	notes->src->lines = NULL;
 }
 
 /* Get the filename:line for the colored entries */
@@ -355,8 +370,8 @@
 	if (!h->sum)
 		return 0;
 
-	src_line = notes->src_line = calloc(len, sizeof(struct source_line));
-	if (!notes->src_line)
+	src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
+	if (!notes->src->lines)
 		return -1;
 
 	start = map->unmap_ip(map, sym->start);
@@ -436,12 +451,12 @@
 	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
 }
 
-int symbol__annotate_printf(struct symbol *sym, struct map *map,
-			    struct list_head *head, int evidx, bool full_paths,
-			    int min_pcnt, int max_lines)
+int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
+			    bool full_paths, int min_pcnt, int max_lines)
 {
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name, *d_filename;
+	struct annotation *notes = symbol__annotation(sym);
 	struct objdump_line *pos;
 	int printed = 2;
 	int more = 0;
@@ -460,8 +475,8 @@
 	if (verbose)
 		symbol__annotate_hits(sym, evidx);
 
-	list_for_each_entry(pos, head, node) {
-		switch (objdump_line__print(pos, head, sym, evidx, len, min_pcnt,
+	list_for_each_entry(pos, &notes->src->source, node) {
+		switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
 					    printed, max_lines)) {
 		case 0:
 			++printed;
@@ -485,11 +500,10 @@
 	struct annotation *notes = symbol__annotation(sym);
 	struct sym_hist *h = annotation__histogram(notes, evidx);
 
-	memset(h, 0, notes->sizeof_sym_hist);
+	memset(h, 0, notes->src->sizeof_sym_hist);
 }
 
-void symbol__annotate_decay_histogram(struct symbol *sym,
-				      struct list_head *head, int evidx)
+void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
 {
 	struct annotation *notes = symbol__annotation(sym);
 	struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -497,7 +511,7 @@
 
 	h->sum = 0;
 
-	list_for_each_entry(pos, head, node) {
+	list_for_each_entry(pos, &notes->src->source, node) {
 		if (pos->offset != -1) {
 			h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
 			h->sum += h->addr[pos->offset];
@@ -522,10 +536,9 @@
 	struct dso *dso = map->dso;
 	const char *filename = dso->long_name;
 	struct rb_root source_line = RB_ROOT;
-	LIST_HEAD(head);
 	u64 len;
 
-	if (symbol__annotate(sym, map, &head, 0) < 0)
+	if (symbol__annotate(sym, map, 0) < 0)
 		return -1;
 
 	len = sym->end - sym->start;
@@ -536,12 +549,12 @@
 		print_summary(&source_line, filename);
 	}
 
-	symbol__annotate_printf(sym, map, &head, evidx, full_paths,
+	symbol__annotate_printf(sym, map, evidx, full_paths,
 				min_pcnt, max_lines);
 	if (print_lines)
 		symbol__free_source_line(sym, len);
 
-	objdump_line_list__purge(&head);
+	objdump_line_list__purge(&symbol__annotation(sym)->src->source);
 
 	return 0;
 }