Эх сурвалжийг харах

Merge tag 'perf-urgent-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent

Pull perf tooling fixes from Arnaldo Carvalho de Melo:

  . Fix a segfault in 'perf top' when kernel map is restricted (Wang Nan)

  . Fix hung wakeup tasks after requeueing in 'perf bench futex' (Davidlohr Bueso)

  . Fix bug in perf probe global variables handling, missing curly braces on
    an if body (He Kuang)

  . 'perf bench numa' fixes (command line help/handling, etc) (Petr Holasek)

  . fix the 'perf kmem' build on RHEL6/OL6 (David Ahern)

  . fix the libtraceevent build on 32-bit arch (Namhyung Kim)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Ingo Molnar 10 жил өмнө
parent
commit
8cc67c3b93

+ 1 - 1
tools/lib/api/Makefile

@@ -16,7 +16,7 @@ MAKEFLAGS += --no-print-directory
 LIBFILE = $(OUTPUT)libapi.a
 LIBFILE = $(OUTPUT)libapi.a
 
 
 CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
 
 
 RM = rm -f
 RM = rm -f

+ 1 - 1
tools/lib/traceevent/event-parse.c

@@ -3865,7 +3865,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
 			} else if (el_size == 4) {
 			} else if (el_size == 4) {
 				trace_seq_printf(s, "%u", *(uint32_t *)num);
 				trace_seq_printf(s, "%u", *(uint32_t *)num);
 			} else if (el_size == 8) {
 			} else if (el_size == 8) {
-				trace_seq_printf(s, "%lu", *(uint64_t *)num);
+				trace_seq_printf(s, "%"PRIu64, *(uint64_t *)num);
 			} else {
 			} else {
 				trace_seq_printf(s, "BAD SIZE:%d 0x%x",
 				trace_seq_printf(s, "BAD SIZE:%d 0x%x",
 						 el_size, *(uint8_t *)num);
 						 el_size, *(uint8_t *)num);

+ 8 - 7
tools/perf/bench/futex-requeue.c

@@ -132,6 +132,9 @@ int bench_futex_requeue(int argc, const char **argv,
 	if (!fshared)
 	if (!fshared)
 		futex_flag = FUTEX_PRIVATE_FLAG;
 		futex_flag = FUTEX_PRIVATE_FLAG;
 
 
+	if (nrequeue > nthreads)
+		nrequeue = nthreads;
+
 	printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
 	printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
 	       "%d at a time.\n\n",  getpid(), nthreads,
 	       "%d at a time.\n\n",  getpid(), nthreads,
 	       fshared ? "shared":"private", &futex1, &futex2, nrequeue);
 	       fshared ? "shared":"private", &futex1, &futex2, nrequeue);
@@ -161,20 +164,18 @@ int bench_futex_requeue(int argc, const char **argv,
 
 
 		/* Ok, all threads are patiently blocked, start requeueing */
 		/* Ok, all threads are patiently blocked, start requeueing */
 		gettimeofday(&start, NULL);
 		gettimeofday(&start, NULL);
-		for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
+		while (nrequeued < nthreads) {
 			/*
 			/*
 			 * Do not wakeup any tasks blocked on futex1, allowing
 			 * Do not wakeup any tasks blocked on futex1, allowing
 			 * us to really measure futex_wait functionality.
 			 * us to really measure futex_wait functionality.
 			 */
 			 */
-			futex_cmp_requeue(&futex1, 0, &futex2, 0,
-					  nrequeue, futex_flag);
+			nrequeued += futex_cmp_requeue(&futex1, 0, &futex2, 0,
+						       nrequeue, futex_flag);
 		}
 		}
+
 		gettimeofday(&end, NULL);
 		gettimeofday(&end, NULL);
 		timersub(&end, &start, &runtime);
 		timersub(&end, &start, &runtime);
 
 
-		if (nrequeued > nthreads)
-			nrequeued = nthreads;
-
 		update_stats(&requeued_stats, nrequeued);
 		update_stats(&requeued_stats, nrequeued);
 		update_stats(&requeuetime_stats, runtime.tv_usec);
 		update_stats(&requeuetime_stats, runtime.tv_usec);
 
 
@@ -184,7 +185,7 @@ int bench_futex_requeue(int argc, const char **argv,
 		}
 		}
 
 
 		/* everybody should be blocked on futex2, wake'em up */
 		/* everybody should be blocked on futex2, wake'em up */
-		nrequeued = futex_wake(&futex2, nthreads, futex_flag);
+		nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
 		if (nthreads != nrequeued)
 		if (nthreads != nrequeued)
 			warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
 			warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
 
 

+ 10 - 2
tools/perf/bench/numa.c

@@ -180,7 +180,7 @@ static const struct option options[] = {
 	OPT_INTEGER('H', "thp"		, &p0.thp,		"MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
 	OPT_INTEGER('H', "thp"		, &p0.thp,		"MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
 	OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
 	OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
 	OPT_BOOLEAN('m', "measure_convergence",	&p0.measure_convergence, "measure convergence latency"),
 	OPT_BOOLEAN('m', "measure_convergence",	&p0.measure_convergence, "measure convergence latency"),
-	OPT_BOOLEAN('q', "quiet"	, &p0.show_quiet,	"bzero the initial allocations"),
+	OPT_BOOLEAN('q', "quiet"	, &p0.show_quiet,	"quiet mode"),
 	OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
 	OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
 
 
 	/* Special option string parsing callbacks: */
 	/* Special option string parsing callbacks: */
@@ -828,6 +828,9 @@ static int count_process_nodes(int process_nr)
 		td = g->threads + task_nr;
 		td = g->threads + task_nr;
 
 
 		node = numa_node_of_cpu(td->curr_cpu);
 		node = numa_node_of_cpu(td->curr_cpu);
+		if (node < 0) /* curr_cpu was likely still -1 */
+			return 0;
+
 		node_present[node] = 1;
 		node_present[node] = 1;
 	}
 	}
 
 
@@ -882,6 +885,11 @@ static void calc_convergence_compression(int *strong)
 	for (p = 0; p < g->p.nr_proc; p++) {
 	for (p = 0; p < g->p.nr_proc; p++) {
 		unsigned int nodes = count_process_nodes(p);
 		unsigned int nodes = count_process_nodes(p);
 
 
+		if (!nodes) {
+			*strong = 0;
+			return;
+		}
+
 		nodes_min = min(nodes, nodes_min);
 		nodes_min = min(nodes, nodes_min);
 		nodes_max = max(nodes, nodes_max);
 		nodes_max = max(nodes, nodes_max);
 	}
 	}
@@ -1395,7 +1403,7 @@ static void print_res(const char *name, double val,
 	if (!name)
 	if (!name)
 		name = "main,";
 		name = "main,";
 
 
-	if (g->p.show_quiet)
+	if (!g->p.show_quiet)
 		printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short);
 		printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short);
 	else
 	else
 		printf(" %14.3f %s\n", val, txt_long);
 		printf(" %14.3f %s\n", val, txt_long);

+ 29 - 29
tools/perf/builtin-kmem.c

@@ -319,7 +319,7 @@ static int page_stat_cmp(struct page_stat *a, struct page_stat *b)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool create)
+static struct page_stat *search_page_alloc_stat(struct page_stat *pstat, bool create)
 {
 {
 	struct rb_node **node = &page_alloc_tree.rb_node;
 	struct rb_node **node = &page_alloc_tree.rb_node;
 	struct rb_node *parent = NULL;
 	struct rb_node *parent = NULL;
@@ -331,7 +331,7 @@ static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool cre
 		parent = *node;
 		parent = *node;
 		data = rb_entry(*node, struct page_stat, node);
 		data = rb_entry(*node, struct page_stat, node);
 
 
-		cmp = page_stat_cmp(data, stat);
+		cmp = page_stat_cmp(data, pstat);
 		if (cmp < 0)
 		if (cmp < 0)
 			node = &parent->rb_left;
 			node = &parent->rb_left;
 		else if (cmp > 0)
 		else if (cmp > 0)
@@ -345,10 +345,10 @@ static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool cre
 
 
 	data = zalloc(sizeof(*data));
 	data = zalloc(sizeof(*data));
 	if (data != NULL) {
 	if (data != NULL) {
-		data->page = stat->page;
-		data->order = stat->order;
-		data->gfp_flags = stat->gfp_flags;
-		data->migrate_type = stat->migrate_type;
+		data->page = pstat->page;
+		data->order = pstat->order;
+		data->gfp_flags = pstat->gfp_flags;
+		data->migrate_type = pstat->migrate_type;
 
 
 		rb_link_node(&data->node, parent, node);
 		rb_link_node(&data->node, parent, node);
 		rb_insert_color(&data->node, &page_alloc_tree);
 		rb_insert_color(&data->node, &page_alloc_tree);
@@ -375,7 +375,7 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
 	unsigned int migrate_type = perf_evsel__intval(evsel, sample,
 	unsigned int migrate_type = perf_evsel__intval(evsel, sample,
 						       "migratetype");
 						       "migratetype");
 	u64 bytes = kmem_page_size << order;
 	u64 bytes = kmem_page_size << order;
-	struct page_stat *stat;
+	struct page_stat *pstat;
 	struct page_stat this = {
 	struct page_stat this = {
 		.order = order,
 		.order = order,
 		.gfp_flags = gfp_flags,
 		.gfp_flags = gfp_flags,
@@ -401,21 +401,21 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
 	 * This is to find the current page (with correct gfp flags and
 	 * This is to find the current page (with correct gfp flags and
 	 * migrate type) at free event.
 	 * migrate type) at free event.
 	 */
 	 */
-	stat = search_page(page, true);
-	if (stat == NULL)
+	pstat = search_page(page, true);
+	if (pstat == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	stat->order = order;
-	stat->gfp_flags = gfp_flags;
-	stat->migrate_type = migrate_type;
+	pstat->order = order;
+	pstat->gfp_flags = gfp_flags;
+	pstat->migrate_type = migrate_type;
 
 
 	this.page = page;
 	this.page = page;
-	stat = search_page_alloc_stat(&this, true);
-	if (stat == NULL)
+	pstat = search_page_alloc_stat(&this, true);
+	if (pstat == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	stat->nr_alloc++;
-	stat->alloc_bytes += bytes;
+	pstat->nr_alloc++;
+	pstat->alloc_bytes += bytes;
 
 
 	order_stats[order][migrate_type]++;
 	order_stats[order][migrate_type]++;
 
 
@@ -428,7 +428,7 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
 	u64 page;
 	u64 page;
 	unsigned int order = perf_evsel__intval(evsel, sample, "order");
 	unsigned int order = perf_evsel__intval(evsel, sample, "order");
 	u64 bytes = kmem_page_size << order;
 	u64 bytes = kmem_page_size << order;
-	struct page_stat *stat;
+	struct page_stat *pstat;
 	struct page_stat this = {
 	struct page_stat this = {
 		.order = order,
 		.order = order,
 	};
 	};
@@ -441,8 +441,8 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
 	nr_page_frees++;
 	nr_page_frees++;
 	total_page_free_bytes += bytes;
 	total_page_free_bytes += bytes;
 
 
-	stat = search_page(page, false);
-	if (stat == NULL) {
+	pstat = search_page(page, false);
+	if (pstat == NULL) {
 		pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
 		pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
 			  page, order);
 			  page, order);
 
 
@@ -453,18 +453,18 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
 	}
 	}
 
 
 	this.page = page;
 	this.page = page;
-	this.gfp_flags = stat->gfp_flags;
-	this.migrate_type = stat->migrate_type;
+	this.gfp_flags = pstat->gfp_flags;
+	this.migrate_type = pstat->migrate_type;
 
 
-	rb_erase(&stat->node, &page_tree);
-	free(stat);
+	rb_erase(&pstat->node, &page_tree);
+	free(pstat);
 
 
-	stat = search_page_alloc_stat(&this, false);
-	if (stat == NULL)
+	pstat = search_page_alloc_stat(&this, false);
+	if (pstat == NULL)
 		return -ENOENT;
 		return -ENOENT;
 
 
-	stat->nr_free++;
-	stat->free_bytes += bytes;
+	pstat->nr_free++;
+	pstat->free_bytes += bytes;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -640,9 +640,9 @@ static void print_page_summary(void)
 	       nr_page_frees, total_page_free_bytes / 1024);
 	       nr_page_frees, total_page_free_bytes / 1024);
 	printf("\n");
 	printf("\n");
 
 
-	printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
+	printf("%-30s: %'16"PRIu64"   [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
 	       nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
 	       nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
-	printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
+	printf("%-30s: %'16"PRIu64"   [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
 	       nr_page_allocs - nr_alloc_freed,
 	       nr_page_allocs - nr_alloc_freed,
 	       (total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
 	       (total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
 	printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total free-only requests",
 	printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total free-only requests",

+ 1 - 1
tools/perf/builtin-top.c

@@ -733,7 +733,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
 "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
 "Check /proc/sys/kernel/kptr_restrict.\n\n"
 "Check /proc/sys/kernel/kptr_restrict.\n\n"
 "Kernel%s samples will not be resolved.\n",
 "Kernel%s samples will not be resolved.\n",
-			  !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
+			  al.map && !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
 			  " modules" : "");
 			  " modules" : "");
 		if (use_browser <= 0)
 		if (use_browser <= 0)
 			sleep(5);
 			sleep(5);

+ 8 - 2
tools/perf/builtin-trace.c

@@ -2241,10 +2241,11 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	if (err < 0)
 	if (err < 0)
 		goto out_error_mmap;
 		goto out_error_mmap;
 
 
+	if (!target__none(&trace->opts.target))
+		perf_evlist__enable(evlist);
+
 	if (forks)
 	if (forks)
 		perf_evlist__start_workload(evlist);
 		perf_evlist__start_workload(evlist);
-	else
-		perf_evlist__enable(evlist);
 
 
 	trace->multiple_threads = evlist->threads->map[0] == -1 ||
 	trace->multiple_threads = evlist->threads->map[0] == -1 ||
 				  evlist->threads->nr > 1 ||
 				  evlist->threads->nr > 1 ||
@@ -2272,6 +2273,11 @@ next_event:
 
 
 			if (interrupted)
 			if (interrupted)
 				goto out_disable;
 				goto out_disable;
+
+			if (done && !draining) {
+				perf_evlist__disable(evlist);
+				draining = true;
+			}
 		}
 		}
 	}
 	}
 
 

+ 3 - 1
tools/perf/util/probe-finder.c

@@ -578,10 +578,12 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 	/* Search child die for local variables and parameters. */
 	/* Search child die for local variables and parameters. */
 	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
 	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
 		/* Search again in global variables */
 		/* Search again in global variables */
-		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
+		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
+						0, &vr_die)) {
 			pr_warning("Failed to find '%s' in this function.\n",
 			pr_warning("Failed to find '%s' in this function.\n",
 				   pf->pvar->var);
 				   pf->pvar->var);
 			ret = -ENOENT;
 			ret = -ENOENT;
+		}
 	}
 	}
 	if (ret >= 0)
 	if (ret >= 0)
 		ret = convert_variable(&vr_die, pf);
 		ret = convert_variable(&vr_die, pf);