Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d7be90e authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Fix modifier to be applied on correct events



The event modifier needs to be applied only on the event definition it
is attached to.

The current state is that in case of multiple events definition (in
single '-e' option, separated by ',') all will get modifier of the last
one.

Fixing this by adding separated list for each event definition, so the
modifier is applied only to proper event(s). Added automated test to
catch this, plus some other modifier tests.

Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1332267341-26338-3-git-send-email-jolsa@redhat.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 9fafd98f
Loading
Loading
Loading
Loading
+114 −2
Original line number Diff line number Diff line
@@ -877,6 +877,58 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
	return test__checkevent_genhw(evlist);
}

static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel = list_entry(evlist->entries.next,
					      struct perf_evsel, node);

	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);

	return test__checkevent_breakpoint(evlist);
}

static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel = list_entry(evlist->entries.next,
					      struct perf_evsel, node);

	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);

	return test__checkevent_breakpoint_x(evlist);
}

static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel = list_entry(evlist->entries.next,
					      struct perf_evsel, node);

	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);

	return test__checkevent_breakpoint_r(evlist);
}

static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel = list_entry(evlist->entries.next,
					      struct perf_evsel, node);

	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);

	return test__checkevent_breakpoint_w(evlist);
}

static int test__checkevent_pmu(struct perf_evlist *evlist)
{

@@ -893,6 +945,47 @@ static int test__checkevent_pmu(struct perf_evlist *evlist)
	return 0;
}

static int test__checkevent_list(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel;

	TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);

	/* r1 */
	evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
	TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
	TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
	TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
	TEST_ASSERT_VAL("wrong config2", 0 == evsel->attr.config2);
	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);

	/* syscalls:sys_enter_open:k */
	evsel = list_entry(evsel->node.next, struct perf_evsel, node);
	TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
	TEST_ASSERT_VAL("wrong sample_type",
		(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
		evsel->attr.sample_type);
	TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);

	/* 1:1:hp */
	evsel = list_entry(evsel->node.next, struct perf_evsel, node);
	TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
	TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
	TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);

	return 0;
}

static struct test__event_st {
	const char *name;
	__u32 type;
@@ -974,10 +1067,30 @@ static struct test__event_st {
		.name  = "L1-dcache-load-miss:kp",
		.check = test__checkevent_genhw_modifier,
	},
	{
		.name  = "mem:0:u",
		.check = test__checkevent_breakpoint_modifier,
	},
	{
		.name  = "mem:0:x:k",
		.check = test__checkevent_breakpoint_x_modifier,
	},
	{
		.name  = "mem:0:r:hp",
		.check = test__checkevent_breakpoint_r_modifier,
	},
	{
		.name  = "mem:0:w:up",
		.check = test__checkevent_breakpoint_w_modifier,
	},
	{
		.name  = "cpu/config=10,config1,config2=3,period=1000/u",
		.check = test__checkevent_pmu,
	},
	{
		.name  = "r1,syscalls:sys_enter_open:k,1:1:hp",
		.check = test__checkevent_list,
	},
};

#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
@@ -1003,10 +1116,9 @@ static int test__parse_events(void)
		}

		ret = e->check(evlist);
		perf_evlist__delete(evlist);
		if (ret)
			break;

		perf_evlist__delete(evlist);
	}

	return ret;
+370 −305

File changed.

Preview size limit exceeded, changes collapsed.

+7 −8
Original line number Diff line number Diff line
/* A Bison parser, made by GNU Bison 2.4.3.  */
/* A Bison parser, made by GNU Bison 2.5.  */

/* Skeleton interface for Bison's Yacc-like parsers in C
/* Bison interface for Yacc-like parsers in C
   
      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
   2009, 2010 Free Software Foundation, Inc.
      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
   
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -59,8 +58,8 @@
typedef union YYSTYPE
{

/* Line 1685 of yacc.c  */
#line 45 "util/parse-events.y"
/* Line 2068 of yacc.c  */
#line 46 "util/parse-events.y"

	char *str;
	unsigned long num;
@@ -69,8 +68,8 @@ typedef union YYSTYPE



/* Line 1685 of yacc.c  */
#line 74 "util/parse-events-bison.h"
/* Line 2068 of yacc.c  */
#line 73 "util/parse-events-bison.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+21 −6
Original line number Diff line number Diff line
@@ -23,7 +23,8 @@ struct event_symbol {
	const char	*alias;
};

int parse_events_parse(struct list_head *list, int *idx);
int parse_events_parse(struct list_head *list, struct list_head *list_tmp,
		       int *idx);

#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
@@ -671,6 +672,18 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
	return add_event(list, idx, &attr, (char *) "pmu");
}

void parse_events_update_lists(struct list_head *list_event,
			       struct list_head *list_all)
{
	/*
	 * Called for single event definition. Update the
	 * 'all event' list, and reinit the 'signle event'
	 * list, for next event definition.
	 */
	list_splice_tail(list_event, list_all);
	INIT_LIST_HEAD(list_event);
}

int parse_events_modifier(struct list_head *list, char *str)
{
	struct perf_evsel *evsel;
@@ -736,14 +749,14 @@ int parse_events_modifier(struct list_head *list, char *str)

int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
{
	struct perf_evsel *evsel, *h;
	LIST_HEAD(list);
	LIST_HEAD(list_tmp);
	YY_BUFFER_STATE buffer;
	int ret, idx = evlist->nr_entries;

	buffer = parse_events__scan_string(str);

	ret = parse_events_parse(&list, &idx);
	ret = parse_events_parse(&list, &list_tmp, &idx);

	parse_events__flush_buffer(buffer);
	parse_events__delete_buffer(buffer);
@@ -754,9 +767,11 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
		return 0;
	}

	list_for_each_entry_safe(evsel, h, &list, node)
		perf_evsel__delete(evsel);

	/*
	 * There are 2 users - builtin-record and builtin-test objects.
	 * Both call perf_evlist__delete in case of error, so we dont
	 * need to bother.
	 */
	fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
	return ret;
+5 −2
Original line number Diff line number Diff line
@@ -76,8 +76,11 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
				void *ptr, char *type);
int parse_events_add_pmu(struct list_head *list, int *idx,
			 char *pmu , struct list_head *head_config);
void parse_events_error(struct list_head *list, int *idx,
			char const *msg);
void parse_events_update_lists(struct list_head *list_event,
			       struct list_head *list_all);
void parse_events_error(struct list_head *list_all,
			struct list_head *list_event,
			int *idx, char const *msg);

void print_events(const char *event_glob);
void print_events_type(u8 type);
Loading