mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	perf hists: Introduce perf_hpp__setup_hists_formats()
The perf_hpp__setup_hists_formats() is to build hists-specific output formats (and sort keys). Currently it's only used in order to build the output format in a hierarchy with same sort keys, but it could be used with different sort keys in non-hierarchy mode later. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1457361308-514-2-git-send-email-namhyung@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
							parent
							
								
									f594bae081
								
							
						
					
					
						commit
						c3bc0c4368
					
				
					 4 changed files with 118 additions and 0 deletions
				
			
		|  | @ -5,6 +5,7 @@ | |||
| #include "../util/util.h" | ||||
| #include "../util/sort.h" | ||||
| #include "../util/evsel.h" | ||||
| #include "../util/evlist.h" | ||||
| 
 | ||||
| /* hist period print (hpp) functions */ | ||||
| 
 | ||||
|  | @ -715,3 +716,65 @@ void perf_hpp__set_user_width(const char *width_list_str) | |||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt) | ||||
| { | ||||
| 	struct perf_hpp_list_node *node = NULL; | ||||
| 	struct perf_hpp_fmt *fmt_copy; | ||||
| 	bool found = false; | ||||
| 
 | ||||
| 	list_for_each_entry(node, &hists->hpp_formats, list) { | ||||
| 		if (node->level == fmt->level) { | ||||
| 			found = true; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!found) { | ||||
| 		node = malloc(sizeof(*node)); | ||||
| 		if (node == NULL) | ||||
| 			return -1; | ||||
| 
 | ||||
| 		node->level = fmt->level; | ||||
| 		perf_hpp_list__init(&node->hpp); | ||||
| 
 | ||||
| 		list_add_tail(&node->list, &hists->hpp_formats); | ||||
| 	} | ||||
| 
 | ||||
| 	fmt_copy = perf_hpp_fmt__dup(fmt); | ||||
| 	if (fmt_copy == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	list_add_tail(&fmt_copy->list, &node->hpp.fields); | ||||
| 	list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, | ||||
| 				  struct perf_evlist *evlist) | ||||
| { | ||||
| 	struct perf_evsel *evsel; | ||||
| 	struct perf_hpp_fmt *fmt; | ||||
| 	struct hists *hists; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!symbol_conf.report_hierarchy) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	evlist__for_each(evlist, evsel) { | ||||
| 		hists = evsel__hists(evsel); | ||||
| 
 | ||||
| 		perf_hpp_list__for_each_sort_list(list, fmt) { | ||||
| 			if (perf_hpp__is_dynamic_entry(fmt) && | ||||
| 			    !perf_hpp__defined_dynamic_entry(fmt, hists)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			ret = add_hierarchy_fmt(hists, fmt); | ||||
| 			if (ret < 0) | ||||
| 				return ret; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -2105,6 +2105,7 @@ int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list) | |||
| 	pthread_mutex_init(&hists->lock, NULL); | ||||
| 	hists->socket_filter = -1; | ||||
| 	hists->hpp_list = hpp_list; | ||||
| 	INIT_LIST_HEAD(&hists->hpp_formats); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -2133,8 +2134,19 @@ static void hists__delete_all_entries(struct hists *hists) | |||
| static void hists_evsel__exit(struct perf_evsel *evsel) | ||||
| { | ||||
| 	struct hists *hists = evsel__hists(evsel); | ||||
| 	struct perf_hpp_fmt *fmt, *pos; | ||||
| 	struct perf_hpp_list_node *node, *tmp; | ||||
| 
 | ||||
| 	hists__delete_all_entries(hists); | ||||
| 
 | ||||
| 	list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) { | ||||
| 		perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) { | ||||
| 			list_del(&fmt->list); | ||||
| 			free(fmt); | ||||
| 		} | ||||
| 		list_del(&node->list); | ||||
| 		free(node); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int hists_evsel__init(struct perf_evsel *evsel) | ||||
|  |  | |||
|  | @ -78,6 +78,7 @@ struct hists { | |||
| 	u16			col_len[HISTC_NR_COLS]; | ||||
| 	int			socket_filter; | ||||
| 	struct perf_hpp_list	*hpp_list; | ||||
| 	struct list_head	hpp_formats; | ||||
| 	int			nr_sort_keys; | ||||
| }; | ||||
| 
 | ||||
|  | @ -244,6 +245,12 @@ struct perf_hpp_list { | |||
| 
 | ||||
| extern struct perf_hpp_list perf_hpp_list; | ||||
| 
 | ||||
| struct perf_hpp_list_node { | ||||
| 	struct list_head	list; | ||||
| 	struct perf_hpp_list	hpp; | ||||
| 	int			level; | ||||
| }; | ||||
| 
 | ||||
| void perf_hpp_list__column_register(struct perf_hpp_list *list, | ||||
| 				    struct perf_hpp_fmt *format); | ||||
| void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, | ||||
|  | @ -299,6 +306,8 @@ void perf_hpp__cancel_cumulate(void); | |||
| void perf_hpp__setup_output_field(struct perf_hpp_list *list); | ||||
| void perf_hpp__reset_output_field(struct perf_hpp_list *list); | ||||
| void perf_hpp__append_sort_keys(struct perf_hpp_list *list); | ||||
| int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, | ||||
| 				  struct perf_evlist *evlist); | ||||
| 
 | ||||
| 
 | ||||
| bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); | ||||
|  | @ -308,6 +317,8 @@ bool perf_hpp__is_trace_entry(struct perf_hpp_fmt *fmt); | |||
| bool perf_hpp__is_srcline_entry(struct perf_hpp_fmt *fmt); | ||||
| bool perf_hpp__is_srcfile_entry(struct perf_hpp_fmt *fmt); | ||||
| 
 | ||||
| struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt); | ||||
| 
 | ||||
| int hist_entry__filter(struct hist_entry *he, int type, const void *arg); | ||||
| 
 | ||||
| static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format, | ||||
|  |  | |||
|  | @ -1908,6 +1908,34 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, | |||
| 	return hde; | ||||
| } | ||||
| 
 | ||||
| struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt) | ||||
| { | ||||
| 	struct perf_hpp_fmt *new_fmt = NULL; | ||||
| 
 | ||||
| 	if (perf_hpp__is_sort_entry(fmt)) { | ||||
| 		struct hpp_sort_entry *hse, *new_hse; | ||||
| 
 | ||||
| 		hse = container_of(fmt, struct hpp_sort_entry, hpp); | ||||
| 		new_hse = memdup(hse, sizeof(*hse)); | ||||
| 		if (new_hse) | ||||
| 			new_fmt = &new_hse->hpp; | ||||
| 	} else if (perf_hpp__is_dynamic_entry(fmt)) { | ||||
| 		struct hpp_dynamic_entry *hde, *new_hde; | ||||
| 
 | ||||
| 		hde = container_of(fmt, struct hpp_dynamic_entry, hpp); | ||||
| 		new_hde = memdup(hde, sizeof(*hde)); | ||||
| 		if (new_hde) | ||||
| 			new_fmt = &new_hde->hpp; | ||||
| 	} else { | ||||
| 		new_fmt = memdup(fmt, sizeof(*fmt)); | ||||
| 	} | ||||
| 
 | ||||
| 	INIT_LIST_HEAD(&new_fmt->list); | ||||
| 	INIT_LIST_HEAD(&new_fmt->sort_list); | ||||
| 
 | ||||
| 	return new_fmt; | ||||
| } | ||||
| 
 | ||||
| static int parse_field_name(char *str, char **event, char **field, char **opt) | ||||
| { | ||||
| 	char *event_name, *field_name, *opt_name; | ||||
|  | @ -2700,6 +2728,10 @@ int setup_sorting(struct perf_evlist *evlist) | |||
| 	/* and then copy output fields to sort keys */ | ||||
| 	perf_hpp__append_sort_keys(&perf_hpp_list); | ||||
| 
 | ||||
| 	/* setup hists-specific output fields */ | ||||
| 	if (perf_hpp__setup_hists_formats(&perf_hpp_list, evlist) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Namhyung Kim
						Namhyung Kim