perf fixes
Subsystems (3)
Linus,
Please pull the latest perf-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf-urgent-for-linus
HEAD: 59cd358a7a5b2f6b61faa01dae6cfda3830ac62a Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Thanks,
Ingo
------------------>
Arnaldo Carvalho de Melo (9):
perf evlist: Explicititely initialize input_name
perf tools: Do not use _FORTIFY_SOURCE when DEBUG=1 is specified perf top: Fix counter name fixup when fallbacking to cpu-clock perf tools: Reconstruct event with modifiers from perf_event_attr perf annotate browser: The idx_asm field should be used in asm only view perf annotate browser: Make feature toggles global
perf config: Allow '_' in config file variable names
perf annotate browser: Read perf config file for settings perf ui browser: Stop using 'self'
Franck Bui-Huu (1):
perf tools: fix thread_map__new_by_pid_str() memory leak in error path
Namhyung Kim (8):
tools lib traceevent: Fix a possible memory leak tools lib traceevent: Fix a possibly wrong memory dereference tools lib traceevent: Fix freeing arg on process_dynamic_array() tools lib traceevent: Use proper function parameter type tools lib traceevent: Fix signature of create_arg_item() tools lib traceevent: Silence compiler warning on 32bit build perf ui: Make --stdio default when TUI is not supported perf tools: Convert critical messages to ui__error()
Stefan Hajnoczi (1):
tools lib traceevent: Allow expressions in __print_symbolic() fields
Stephane Eranian (1):
perf record: Fix branch_stack type in perf_record_opts
Steven Rostedt (1):
ring-buffer: Check for valid buffer before changing size
kernel/trace/ring_buffer.c | 5 + tools/lib/traceevent/event-parse.c | 22 +- tools/lib/traceevent/parse-filter.c | 7 +- tools/perf/Documentation/perfconfig.example | 8 + tools/perf/Makefile | 4 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-evlist.c | 2 +- tools/perf/builtin-record.c | 14 +- tools/perf/builtin-report.c | 14 +- tools/perf/builtin-top.c | 24 +- tools/perf/perf.h | 2 +- tools/perf/ui/browser.c | 182 +++++++-------- tools/perf/ui/browser.h | 1 + tools/perf/ui/browsers/annotate.c | 262 +++++++++++++-------- tools/perf/ui/browsers/hists.c | 338 ++++++++++++++-------------- tools/perf/ui/setup.c | 1 + tools/perf/util/config.c | 2 +- tools/perf/util/evsel.c | 90 ++++++++ tools/perf/util/evsel.h | 3 + tools/perf/util/parse-events.c | 27 +-- tools/perf/util/thread_map.c | 21 +- 21 files changed, 615 insertions(+), 416 deletions(-)
kernel/trace/ring_buffer.c +5 -0
@@ -1486,6 +1486,11 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,if (!buffer)return size; +/* Make sure the requested buffer exists */ +if (cpu_id !=RING_BUFFER_ALL_CPUS && + !cpumask_test_cpu (cpu_id, buffer->cpumask)) +return size; + size =DIV_ROUND_UP (size,BUF_PAGE_SIZE ); size *=BUF_PAGE_SIZE ;
tools/lib/traceevent/event-parse.c +18 -4
@@ -1434,8 +1434,11 @@ static int event_read_fields(struct event_format *event, struct format_field **f fail:free_token (token); fail_expect: -if (field) +if (field) { +free (field->type); +free (field->name);free (field); + }return -1 ; }
@@ -1712,6 +1715,8 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)if (set_op_prio (arg) ==-1 ) { event->flags |=EVENT_FL_FAILED ; +/* arg->op.op (= token) will be freed at out_free */ + arg->op.op =NULL ; goto out_free; }
@@ -2124,6 +2129,13 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **free_token (token); type =process_arg (event, arg, &token); + +if (type ==EVENT_OP ) + type =process_op (event, arg, &token); + +if (type ==EVENT_ERROR ) + goto out_free; +if (test_type_token (type, token,EVENT_DELIM ,"," )) goto out_free;
@@ -2288,17 +2300,18 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char ** arg =alloc_arg (); type =process_arg (event, arg, &token);if (type ==EVENT_ERROR ) - goto out_free; + goto out_free_arg;if (!test_type_token (type, token,EVENT_OP ,"]" )) - goto out_free; + goto out_free_arg;free_token (token); type =read_token_item (tok);return type; + out_free_arg: +free_arg (arg); out_free: -free (arg);free_token (token); *tok =NULL ;return EVENT_ERROR ;
@@ -3362,6 +3375,7 @@ process_defined_func(struct trace_seq *s, void *data, int size,break ; } farg = farg->next; + param = param->next; } ret = (*func_handle->func)(s, args);
tools/lib/traceevent/parse-filter.c +3 -4
@@ -325,9 +325,8 @@ static void free_events(struct event_list *events) }static struct filter_arg * -create_arg_item (struct event_format *event, -const char *token,enum filter_arg_type type, -char **error_str) +create_arg_item (struct event_format *event,const char *token, +enum event_type type,char **error_str) {struct format_field *field;struct filter_arg *arg;
@@ -1585,7 +1584,7 @@ get_value(struct event_format *event,const char *name; name =get_comm (event, record); -return (unsigned long long )name; +return (unsigned long )name; }pevent_read_number_field (field, record->data, &val);
tools/perf/Documentation/perfconfig.example +8 -0
@@ -19,3 +19,11 @@ # Default, disable using /dev/null dir = /root/.debug + +[annotate] + + # Defaults + hide_src_code = false + use_offset = true + jump_arrows = true + show_nr_jumps = false
tools/perf/Makefile +2 -2
@@ -80,7 +80,7 @@ ifeq ("$(origin DEBUG)", "command line") PERF_DEBUG = $(DEBUG) endif ifndef PERF_DEBUG - CFLAGS_OPTIMIZE = -O6 + CFLAGS_OPTIMIZE = -O6 -D_FORTIFY_SOURCE=2 endif ifdef PARSER_DEBUG
@@ -89,7 +89,7 @@ ifdef PARSER_DEBUG PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG endif -CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) +CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS)
tools/perf/builtin-annotate.c +1 -1
@@ -215,7 +215,7 @@ static int __cmd_annotate(struct perf_annotate *ann) }if (total_nr_samples ==0 ) { -ui__warning ("The %s file has no samples!\n" , session->filename); +ui__error ("The %s file has no samples!\n" , session->filename); goto out_delete; } out_delete:
tools/perf/builtin-evlist.c +1 -1
@@ -116,7 +116,7 @@ static const char * const evlist_usage[] = {int cmd_evlist (int argc,const char **argv,const char *prefix__used ) {struct perf_attr_details details = { .verbose = false, }; -const char *input_name; +const char *input_name =NULL ;const struct option options[] = {OPT_STRING ('i' ,"input" , &input_name,"file" ,"Input file name" ),
tools/perf/builtin-record.c +7 -7
@@ -264,7 +264,7 @@ try_again: }if (err ==ENOENT ) { -ui__warning ("The %s event is not supported.\n" , +ui__error ("The %s event is not supported.\n" ,event_name (pos));exit (EXIT_FAILURE ); }
@@ -858,8 +858,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)usage_with_options (record_usage, record_options);if (rec->force && rec->append_file) { -fprintf (stderr,"Can't overwrite and append at the same time." -" You need to choose between -f and -A" ); +ui__error ("Can't overwrite and append at the same time." +" You need to choose between -f and -A" );usage_with_options (record_usage, record_options); }else if (rec->append_file) { rec->write_mode =WRITE_APPEND ;
@@ -868,8 +868,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) }if (nr_cgroups && !rec->opts.target.system_wide) { -fprintf (stderr,"cgroup monitoring only available in" -" system-wide mode\n" ); +ui__error ("cgroup monitoring only available in" +" system-wide mode\n" );usage_with_options (record_usage, record_options); }
@@ -905,7 +905,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)int saved_errno = errno;perf_target__strerror (&rec->opts.target, err, errbuf,BUFSIZ ); -ui__warning ("%s" , errbuf); +ui__error ("%s" , errbuf); err = -saved_errno; goto out_free_fd;
@@ -933,7 +933,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)else if (rec->opts.freq) { rec->opts.default_interval = rec->opts.freq; }else { -fprintf (stderr,"frequency and count are zero, aborting\n" ); +ui__error ("frequency and count are zero, aborting\n" ); err = -EINVAL ; goto out_free_fd; }
tools/perf/builtin-report.c +6 -8
@@ -251,13 +251,13 @@ static int perf_report__setup_sample_type(struct perf_report *rep)if (!(self->sample_type &PERF_SAMPLE_CALLCHAIN )) {if (sort__has_parent) { -ui__warning ("Selected --sort parent, but no " +ui__error ("Selected --sort parent, but no " "callchain data. Did you call " "'perf record' without -g?\n" );return -EINVAL ; }if (symbol_conf.use_callchain) { -ui__warning ("Selected -g but no callchain data. Did " +ui__error ("Selected -g but no callchain data. Did " "you call 'perf record' without -g?\n" );return -1 ; }
@@ -266,17 +266,15 @@ static int perf_report__setup_sample_type(struct perf_report *rep) !symbol_conf.use_callchain) { symbol_conf.use_callchain = true;if (callchain_register_param (&callchain_param) <0 ) { -ui__warning ("Can't register callchain " -"params.\n" ); +ui__error ("Can't register callchain params.\n" );return -EINVAL ; } }if (sort__branch_mode ==1 ) {if (!(self->sample_type &PERF_SAMPLE_BRANCH_STACK )) { -fprintf (stderr,"selected -b but no branch data." -" Did you call perf record without" -" -b?\n" ); +ui__error ("Selected -b but no branch data. " +"Did you call perf record without -b?\n" );return -1 ; } }
@@ -420,7 +418,7 @@ static int __cmd_report(struct perf_report *rep) }if (nr_samples ==0 ) { -ui__warning ("The %s file has no samples!\n" , session->filename); +ui__error ("The %s file has no samples!\n" , session->filename); goto out_delete; }
tools/perf/builtin-top.c +12 -12
@@ -953,22 +953,22 @@ try_again: attr->config =PERF_COUNT_SW_CPU_CLOCK ;if (counter->name) {free (counter->name); - counter->name =strdup (event_name (counter)); + counter->name =NULL ; } goto try_again; }if (err ==ENOENT ) { -ui__warning ("The %s event is not supported.\n" , +ui__error ("The %s event is not supported.\n" ,event_name (counter)); goto out_err; }else if (err ==EMFILE ) { -ui__warning ("Too many events are opened.\n" +ui__error ("Too many events are opened.\n" "Try again after reducing the number of events\n" ); goto out_err; } -ui__warning ("The sys_perf_event_open() syscall " +ui__error ("The sys_perf_event_open() syscall " "returned with %d (%s). /bin/dmesg " "may provide additional information.\n" "No CONFIG_PERF_EVENTS=y kernel support "
@@ -978,7 +978,7 @@ try_again: }if (perf_evlist__mmap (evlist, top->mmap_pages, false) <0 ) { -ui__warning ("Failed to mmap with %d (%s)\n" , +ui__error ("Failed to mmap with %d (%s)\n" , errno,strerror (errno)); goto out_err; }
@@ -994,12 +994,12 @@ static int perf_top__setup_sample_type(struct perf_top *top) {if (!top->sort_has_symbols) {if (symbol_conf.use_callchain) { -ui__warning ("Selected -g but \"sym\" not present in --sort/-s." ); +ui__error ("Selected -g but \"sym\" not present in --sort/-s." );return -EINVAL ; } }else if (!top->dont_use_callchains && callchain_param.mode !=CHAIN_NONE ) {if (callchain_register_param (&callchain_param) <0 ) { -ui__warning ("Can't register callchain params.\n" ); +ui__error ("Can't register callchain params.\n" );return -EINVAL ; } }
@@ -1041,7 +1041,7 @@ static int __cmd_top(struct perf_top *top)if (pthread_create (&thread,NULL , (use_browser >0 ? display_thread_tui : display_thread), top)) { -printf ("Could not create display thread.\n" ); +ui__error ("Could not create display thread.\n" );exit (-1 ); }
@@ -1050,7 +1050,7 @@ static int __cmd_top(struct perf_top *top) param.sched_priority = top->realtime_prio;if (sched_setscheduler (0 ,SCHED_FIFO , ¶m)) { -printf ("Could not set realtime priority.\n" ); +ui__error ("Could not set realtime priority.\n" );exit (-1 ); } }
@@ -1274,7 +1274,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)int saved_errno = errno;perf_target__strerror (&top.target, status, errbuf,BUFSIZ ); -ui__warning ("%s" , errbuf); +ui__error ("%s" , errbuf); status = -saved_errno; goto out_delete_evlist;
@@ -1288,7 +1288,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)if (!top.evlist->nr_entries &&perf_evlist__add_default (top.evlist) <0 ) { -pr_err ("Not enough memory for event selector list\n" ); +ui__error ("Not enough memory for event selector list\n" );return -ENOMEM ; }
@@ -1305,7 +1305,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)else if (top.freq) { top.default_interval = top.freq; }else { -fprintf (stderr,"frequency and count are zero, aborting\n" ); +ui__error ("frequency and count are zero, aborting\n" );exit (EXIT_FAILURE ); }
tools/perf/perf.h +1 -1
@@ -227,7 +227,7 @@ struct perf_record_opts {unsigned int freq;unsigned int mmap_pages;unsigned int user_freq; -int branch_stack; +u64 branch_stack;u64 default_interval;u64 user_interval; };
tools/perf/ui/browser.c +92 -90
349 lines not on this page · raw message
tools/perf/ui/browser.h +1 -0
@@ -69,4 +69,5 @@ void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whencunsigned int ui_browser__list_head_refresh (struct ui_browser *self);void ui_browser__init (void ); +void annotate_browser__init (void );#endif /* _PERF_UI_BROWSER_H_ */
tools/perf/ui/browsers/annotate.c +173 -89
506 lines not on this page · raw message
tools/perf/ui/browsers/hists.c +169 -169
757 lines not on this page · raw message
tools/perf/ui/setup.c +1 -0
@@ -22,6 +22,7 @@ void setup_browser(bool fallback_to_pager)break ;/* fall through */ default : + use_browser =0 ;if (fallback_to_pager)setup_pager ();break ;
tools/perf/util/config.c +1 -1
@@ -120,7 +120,7 @@ static char *parse_value(void)static inline int iskeychar (int c) { -return isalnum (c) || c =='-' ; +return isalnum (c) || c =='-' || c =='_' ; }static int get_value (config_fn_t fn,void *data,char *name,unsigned int len)
tools/perf/util/evsel.c +90 -0
102 lines not on this page · raw message
tools/perf/util/evsel.h +3 -0
@@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel,struct perf_record_opts *opts, struct perf_evsel *first); +const char *__perf_evsel__hw_name (u64 config); +int perf_evsel__name (struct perf_evsel *evsel,char *bf,size_t size); +int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);
tools/perf/util/parse-events.c +11 -16
@@ -62,19 +62,6 @@ static struct event_symbol event_symbols[] = {#define PERF_EVENT_TYPE (config) __PERF_EVENT_FIELD(config, TYPE)#define PERF_EVENT_ID (config) __PERF_EVENT_FIELD(config, EVENT) -static const char *hw_event_names[PERF_COUNT_HW_MAX ] = { -"cycles" , -"instructions" , -"cache-references" , -"cache-misses" , -"branches" , -"branch-misses" , -"bus-cycles" , -"stalled-cycles-frontend" , -"stalled-cycles-backend" , -"ref-cycles" , -}; -static const char *sw_event_names[PERF_COUNT_SW_MAX ] = {"cpu-clock" ,"task-clock" ,
@@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel)u64 config = evsel->attr.config;int type = evsel->attr.type; +if (type ==PERF_TYPE_RAW || type ==PERF_TYPE_HARDWARE ) { +/* +* XXX minimal fix, see comment on perf_evsen__name, this static buffer +* will go away together with event_name in the next devel cycle. +*/ +static char bf[128 ]; +perf_evsel__name (evsel, bf,sizeof (bf)); +return bf; + } +if (evsel->name)return evsel->name;
@@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config)switch (type) {case PERF_TYPE_HARDWARE : -if (config <PERF_COUNT_HW_MAX && hw_event_names[config]) -return hw_event_names[config]; -return "unknown-hardware" ; +return __perf_evsel__hw_name (config);case PERF_TYPE_HW_CACHE : {u8 cache_type, cache_op, cache_result;
tools/perf/util/thread_map.c +10 -11
@@ -188,28 +188,27 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) nt =realloc (threads, (sizeof (*threads) +sizeof (pid_t) * total_tasks));if (nt ==NULL ) - goto out_free_threads; + goto out_free_namelist; threads = nt; -if (threads) { -for (i =0 ; i < items; i++) - threads->map[j++] =atoi (namelist[i]->d_name); - threads->nr = total_tasks; - } - -for (i =0 ; i < items; i++) +for (i =0 ; i < items; i++) { + threads->map[j++] =atoi (namelist[i]->d_name);free (namelist[i]); + } + threads->nr = total_tasks;free (namelist); - -if (!threads) -break ; } out:strlist__delete (slist);return threads; +out_free_namelist: +for (i =0 ; i < items; i++) +free (namelist[i]); +free (namelist); + out_free_threads:free (threads); threads =NULL ;