diff options
| author | David S. Miller <davem@davemloft.net> | 2012-10-02 23:02:10 -0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-10-02 23:02:10 -0400 | 
| commit | 954f9ac43b87b44152b8c21163cefd466a87145e (patch) | |
| tree | 31c4197f975c66c96976948663e6ce844900b41a /tools/perf/util/parse-events.c | |
| parent | 1b62ca7bf5775bed048032b7e779561e1fe66aa0 (diff) | |
| parent | 7fe0b14b725d6d09a1d9e1409bd465cb88b587f9 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
There's a Niagara 2 memcpy fix in this tree and I have
a Kconfig fix from Dave Jones which requires the sparc-next
changes which went upstream yesterday.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/perf/util/parse-events.c')
| -rw-r--r-- | tools/perf/util/parse-events.c | 254 | 
1 files changed, 173 insertions, 81 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 74a5af4d33ec..aed38e4b9dfa 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -239,8 +239,11 @@ const char *event_type(int type)  	return "unknown";  } -static int add_event(struct list_head **_list, int *idx, -		     struct perf_event_attr *attr, char *name) + + +static int __add_event(struct list_head **_list, int *idx, +		       struct perf_event_attr *attr, +		       char *name, struct cpu_map *cpus)  {  	struct perf_evsel *evsel;  	struct list_head *list = *_list; @@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx,  		return -ENOMEM;  	} +	evsel->cpus = cpus;  	if (name)  		evsel->name = strdup(name);  	list_add_tail(&evsel->node, list); @@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx,  	return 0;  } +static int add_event(struct list_head **_list, int *idx, +		     struct perf_event_attr *attr, char *name) +{ +	return __add_event(_list, idx, attr, name, NULL); +} +  static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)  {  	int i, j; @@ -308,7 +318,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,  	for (i = 0; (i < 2) && (op_result[i]); i++) {  		char *str = op_result[i]; -		snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); +		n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);  		if (cache_op == -1) {  			cache_op = parse_aliases(str, perf_evsel__hw_cache_op, @@ -346,42 +356,28 @@ int parse_events_add_cache(struct list_head **list, int *idx,  	return add_event(list, idx, &attr, name);  } -static int add_tracepoint(struct list_head **list, int *idx, +static int add_tracepoint(struct list_head **listp, int *idx,  			  char *sys_name, char *evt_name)  { -	struct perf_event_attr attr; -	char name[MAX_NAME_LEN]; -	char evt_path[MAXPATHLEN]; -	char id_buf[4]; -	u64 id; -	int fd; - -	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path, -		 sys_name, evt_name); - -	fd = open(evt_path, O_RDONLY); -	if (fd < 0) -		return -1; +	struct perf_evsel *evsel; +	struct list_head *list = *listp; -	if (read(fd, id_buf, sizeof(id_buf)) < 0) { -		close(fd); -		return -1; +	if (!list) { +		list = malloc(sizeof(*list)); +		if (!list) +			return -ENOMEM; +		INIT_LIST_HEAD(list);  	} -	close(fd); -	id = atoll(id_buf); - -	memset(&attr, 0, sizeof(attr)); -	attr.config = id; -	attr.type = PERF_TYPE_TRACEPOINT; -	attr.sample_type |= PERF_SAMPLE_RAW; -	attr.sample_type |= PERF_SAMPLE_TIME; -	attr.sample_type |= PERF_SAMPLE_CPU; -	attr.sample_type |= PERF_SAMPLE_PERIOD; -	attr.sample_period = 1; +	evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); +	if (!evsel) { +		free(list); +		return -ENOMEM; +	} -	snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); -	return add_event(list, idx, &attr, name); +	list_add_tail(&evsel->node, list); +	*listp = list; +	return 0;  }  static int add_tracepoint_multi(struct list_head **list, int *idx, @@ -551,7 +547,7 @@ static int config_attr(struct perf_event_attr *attr,  }  int parse_events_add_numeric(struct list_head **list, int *idx, -			     unsigned long type, unsigned long config, +			     u32 type, u64 config,  			     struct list_head *head_config)  {  	struct perf_event_attr attr; @@ -607,8 +603,23 @@ int parse_events_add_pmu(struct list_head **list, int *idx,  	if (perf_pmu__config(pmu, &attr, head_config))  		return -EINVAL; -	return add_event(list, idx, &attr, -			 pmu_event_name(head_config)); +	return __add_event(list, idx, &attr, pmu_event_name(head_config), +			   pmu->cpus); +} + +int parse_events__modifier_group(struct list_head *list, +				 char *event_mod) +{ +	return parse_events__modifier_event(list, event_mod, true); +} + +void parse_events__set_leader(char *name, struct list_head *list) +{ +	struct perf_evsel *leader; + +	__perf_evlist__set_leader(list); +	leader = list_entry(list->next, struct perf_evsel, node); +	leader->group_name = name ? strdup(name) : NULL;  }  void parse_events_update_lists(struct list_head *list_event, @@ -616,21 +627,45 @@ void parse_events_update_lists(struct list_head *list_event,  {  	/*  	 * Called for single event definition. Update the -	 * 'all event' list, and reinit the 'signle event' +	 * 'all event' list, and reinit the 'single event'  	 * list, for next event definition.  	 */  	list_splice_tail(list_event, list_all);  	free(list_event);  } -int parse_events_modifier(struct list_head *list, char *str) +struct event_modifier { +	int eu; +	int ek; +	int eh; +	int eH; +	int eG; +	int precise; +	int exclude_GH; +}; + +static int get_event_modifier(struct event_modifier *mod, char *str, +			       struct perf_evsel *evsel)  { -	struct perf_evsel *evsel; -	int exclude = 0, exclude_GH = 0; -	int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; +	int eu = evsel ? evsel->attr.exclude_user : 0; +	int ek = evsel ? evsel->attr.exclude_kernel : 0; +	int eh = evsel ? evsel->attr.exclude_hv : 0; +	int eH = evsel ? evsel->attr.exclude_host : 0; +	int eG = evsel ? evsel->attr.exclude_guest : 0; +	int precise = evsel ? evsel->attr.precise_ip : 0; -	if (str == NULL) -		return 0; +	int exclude = eu | ek | eh; +	int exclude_GH = evsel ? evsel->exclude_GH : 0; + +	/* +	 * We are here for group and 'GH' was not set as event +	 * modifier and whatever event/group modifier override +	 * default 'GH' setup. +	 */ +	if (evsel && !exclude_GH) +		eH = eG = 0; + +	memset(mod, 0, sizeof(*mod));  	while (*str) {  		if (*str == 'u') { @@ -674,13 +709,51 @@ int parse_events_modifier(struct list_head *list, char *str)  	if (precise > 3)  		return -EINVAL; +	mod->eu = eu; +	mod->ek = ek; +	mod->eh = eh; +	mod->eH = eH; +	mod->eG = eG; +	mod->precise = precise; +	mod->exclude_GH = exclude_GH; +	return 0; +} + +int parse_events__modifier_event(struct list_head *list, char *str, bool add) +{ +	struct perf_evsel *evsel; +	struct event_modifier mod; + +	if (str == NULL) +		return 0; + +	if (!add && get_event_modifier(&mod, str, NULL)) +		return -EINVAL; +  	list_for_each_entry(evsel, list, node) { -		evsel->attr.exclude_user   = eu; -		evsel->attr.exclude_kernel = ek; -		evsel->attr.exclude_hv     = eh; -		evsel->attr.precise_ip     = precise; -		evsel->attr.exclude_host   = eH; -		evsel->attr.exclude_guest  = eG; + +		if (add && get_event_modifier(&mod, str, evsel)) +			return -EINVAL; + +		evsel->attr.exclude_user   = mod.eu; +		evsel->attr.exclude_kernel = mod.ek; +		evsel->attr.exclude_hv     = mod.eh; +		evsel->attr.precise_ip     = mod.precise; +		evsel->attr.exclude_host   = mod.eH; +		evsel->attr.exclude_guest  = mod.eG; +		evsel->exclude_GH          = mod.exclude_GH; +	} + +	return 0; +} + +int parse_events_name(struct list_head *list, char *name) +{ +	struct perf_evsel *evsel; + +	list_for_each_entry(evsel, list, node) { +		if (!evsel->name) +			evsel->name = strdup(name);  	}  	return 0; @@ -730,7 +803,8 @@ int parse_events_terms(struct list_head *terms, const char *str)  	return ret;  } -int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) +int parse_events(struct perf_evlist *evlist, const char *str, +		 int unset __maybe_unused)  {  	struct parse_events_data__events data = {  		.list = LIST_HEAD_INIT(data.list), @@ -756,20 +830,20 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)  }  int parse_events_option(const struct option *opt, const char *str, -			int unset __used) +			int unset __maybe_unused)  {  	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;  	return parse_events(evlist, str, unset);  }  int parse_filter(const struct option *opt, const char *str, -		 int unset __used) +		 int unset __maybe_unused)  {  	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;  	struct perf_evsel *last = NULL;  	if (evlist->nr_entries > 0) -		last = list_entry(evlist->entries.prev, struct perf_evsel, node); +		last = perf_evlist__last(evlist);  	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {  		fprintf(stderr, @@ -799,7 +873,8 @@ static const char * const event_type_descriptors[] = {   * Print the events from <debugfs_mount_point>/tracing/events   */ -void print_tracepoint_events(const char *subsys_glob, const char *event_glob) +void print_tracepoint_events(const char *subsys_glob, const char *event_glob, +			     bool name_only)  {  	DIR *sys_dir, *evt_dir;  	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; @@ -829,6 +904,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)  			    !strglobmatch(evt_dirent.d_name, event_glob))  				continue; +			if (name_only) { +				printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); +				continue; +			} +  			snprintf(evt_path, MAXPATHLEN, "%s:%s",  				 sys_dirent.d_name, evt_dirent.d_name);  			printf("  %-50s [%s]\n", evt_path, @@ -906,7 +986,7 @@ void print_events_type(u8 type)  		__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);  } -int print_hwcache_events(const char *event_glob) +int print_hwcache_events(const char *event_glob, bool name_only)  {  	unsigned int type, op, i, printed = 0;  	char name[64]; @@ -923,8 +1003,11 @@ int print_hwcache_events(const char *event_glob)  				if (event_glob != NULL && !strglobmatch(name, event_glob))  					continue; -				printf("  %-50s [%s]\n", name, -					event_type_descriptors[PERF_TYPE_HW_CACHE]); +				if (name_only) +					printf("%s ", name); +				else +					printf("  %-50s [%s]\n", name, +					       event_type_descriptors[PERF_TYPE_HW_CACHE]);  				++printed;  			}  		} @@ -934,7 +1017,8 @@ int print_hwcache_events(const char *event_glob)  }  static void print_symbol_events(const char *event_glob, unsigned type, -				struct event_symbol *syms, unsigned max) +				struct event_symbol *syms, unsigned max, +				bool name_only)  {  	unsigned i, printed = 0;  	char name[MAX_NAME_LEN]; @@ -946,6 +1030,11 @@ static void print_symbol_events(const char *event_glob, unsigned type,  		      (syms->alias && strglobmatch(syms->alias, event_glob))))  			continue; +		if (name_only) { +			printf("%s ", syms->symbol); +			continue; +		} +  		if (strlen(syms->alias))  			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);  		else @@ -963,39 +1052,42 @@ static void print_symbol_events(const char *event_glob, unsigned type,  /*   * Print the help text for the event symbols:   */ -void print_events(const char *event_glob) +void print_events(const char *event_glob, bool name_only)  { - -	printf("\n"); -	printf("List of pre-defined events (to be used in -e):\n"); +	if (!name_only) { +		printf("\n"); +		printf("List of pre-defined events (to be used in -e):\n"); +	}  	print_symbol_events(event_glob, PERF_TYPE_HARDWARE, -			    event_symbols_hw, PERF_COUNT_HW_MAX); +			    event_symbols_hw, PERF_COUNT_HW_MAX, name_only);  	print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, -			    event_symbols_sw, PERF_COUNT_SW_MAX); +			    event_symbols_sw, PERF_COUNT_SW_MAX, name_only); -	print_hwcache_events(event_glob); +	print_hwcache_events(event_glob, name_only);  	if (event_glob != NULL)  		return; -	printf("\n"); -	printf("  %-50s [%s]\n", -	       "rNNN", -	       event_type_descriptors[PERF_TYPE_RAW]); -	printf("  %-50s [%s]\n", -	       "cpu/t1=v1[,t2=v2,t3 ...]/modifier", -	       event_type_descriptors[PERF_TYPE_RAW]); -	printf("   (see 'perf list --help' on how to encode it)\n"); -	printf("\n"); - -	printf("  %-50s [%s]\n", -			"mem:<addr>[:access]", +	if (!name_only) { +		printf("\n"); +		printf("  %-50s [%s]\n", +		       "rNNN", +		       event_type_descriptors[PERF_TYPE_RAW]); +		printf("  %-50s [%s]\n", +		       "cpu/t1=v1[,t2=v2,t3 ...]/modifier", +		       event_type_descriptors[PERF_TYPE_RAW]); +		printf("   (see 'perf list --help' on how to encode it)\n"); +		printf("\n"); + +		printf("  %-50s [%s]\n", +		       "mem:<addr>[:access]",  			event_type_descriptors[PERF_TYPE_BREAKPOINT]); -	printf("\n"); +		printf("\n"); +	} -	print_tracepoint_events(NULL, NULL); +	print_tracepoint_events(NULL, NULL, name_only);  }  int parse_events__is_hardcoded_term(struct parse_events__term *term) @@ -1005,7 +1097,7 @@ int parse_events__is_hardcoded_term(struct parse_events__term *term)  static int new_term(struct parse_events__term **_term, int type_val,  		    int type_term, char *config, -		    char *str, long num) +		    char *str, u64 num)  {  	struct parse_events__term *term; @@ -1034,7 +1126,7 @@ static int new_term(struct parse_events__term **_term, int type_val,  }  int parse_events__term_num(struct parse_events__term **term, -			   int type_term, char *config, long num) +			   int type_term, char *config, u64 num)  {  	return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,  			config, NULL, num);  | 
