perf/core improvements and fixes
Jiri Olsa
reviewerhi Ingo,
please consider pulling
thanks,
jirka
The following changes since commit e450f90e8c7d0bf70519223c1b848446ae63f313:
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core (2014-05-22 11:37:40 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git tags/perf-core-for-mingo
for you to fetch changes up to 34cfec19bd8496279d283498b97069d9a0f7e130:
tools lib traceevent: Added support for __get_bitmask() macro (2014-05-28 15:08:26 +0200)
----------------------------------------------------------------
perf/core improvements and fixes:
. Added support for __get_bitmask() macro to traceevent library (Steven Rostedt)
. Allow overriding sysfs and proc finding with env var (Cody P Schafer)
. Consider header files outside perf directory in tags target (Sebastian Andrzej Siewior)
. Add warning when disabling perl scripting support due to missing devel files (Arnaldo Carvalho de Melo)
. Warn the user when trace command is not available (Arnaldo Carvalho de Melo)
. Pass protection and flags bits through mmap2 interface (Peter Zijlstra)
. Update perf tool mmap2 interface with protection and flag bits (Don Zickus)
. Re-enable mmap interface (Don Zickus)
. Add mem-mode documentation to report command (Don Zickus)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (2):
perf trace: Warn the user when not available
perf tools: Add warning when disabling perl scripting support due to missing devel files
Cody P Schafer (1):
perf tools: Allow overriding sysfs and proc finding with env var
Don Zickus (3):
Revert "perf: Disable PERF_RECORD_MMAP2 support"
perf tools: Update mmap2 interface with protection and flag bits perf report: Add mem-mode documentation to report command
Peter Zijlstra (1):
perf: Pass protection and flags bits through mmap2 interface
Sebastian Andrzej Siewior (1):
perf tools: Consider header files outside perf directory in tags target
Steven Rostedt (Red Hat) (1):
tools lib traceevent: Added support for __get_bitmask() macro
include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 37 ++++++- tools/lib/api/fs/fs.c | 43 +++++++- tools/lib/traceevent/event-parse.c | 113 +++++++++++++++++++++ tools/lib/traceevent/event-parse.h | 7 ++ tools/perf/Documentation/perf-report.txt | 22 ++++ tools/perf/Makefile.perf | 9 +- tools/perf/config/Makefile | 1 + tools/perf/perf.c | 8 +- tools/perf/tests/dwarf-unwind.c | 2 +- tools/perf/util/event.c | 59 +++++++---- tools/perf/util/event.h | 2 + tools/perf/util/evsel.c | 1 + tools/perf/util/machine.c | 4 +- tools/perf/util/map.c | 4 +- tools/perf/util/map.h | 4 +- .../perf/util/scripting-engines/trace-event-perl.c | 1 + .../util/scripting-engines/trace-event-python.c | 1 + 18 files changed, 286 insertions(+), 33 deletions(-)
Jiri Olsa
reviewerPATCH 1/9 perf: Pass protection and flags bits through mmap2 interface
From: Peter Zijlstra <[email protected]>
The mmap2 interface was missing the protection and flags bits needed to accurately determine if a mmap memory area was shared or private and if it was readable or not.
--- include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
include/uapi/linux/perf_event.h +1 -0
@@ -699,6 +699,7 @@ enum perf_event_type {* u32 min; * u64 ino; * u64 ino_generation; +* u32 prot, flags; * char filename[]; * struct sample_id sample_id; * };
kernel/events/core.c +33 -0
@@ -40,6 +40,7 @@#include <linux/mm_types.h> #include <linux/cgroup.h> #include <linux/module.h> +#include <linux/mman.h> #include "internal.h"
@@ -5116,6 +5117,7 @@ struct perf_mmap_event {int maj, min;u64 ino;u64 ino_generation; +u32 prot, flags;struct {struct perf_event_header header;
@@ -5157,6 +5159,8 @@ static void perf_event_mmap_output(struct perf_event *event, mmap_event->event_id.header.size +=sizeof (mmap_event->min); mmap_event->event_id.header.size +=sizeof (mmap_event->ino); mmap_event->event_id.header.size +=sizeof (mmap_event->ino_generation); + mmap_event->event_id.header.size +=sizeof (mmap_event->prot); + mmap_event->event_id.header.size +=sizeof (mmap_event->flags); }perf_event_header__init_id (&mmap_event->event_id.header, &sample, event);
@@ -5175,6 +5179,8 @@ static void perf_event_mmap_output(struct perf_event *event,perf_output_put (&handle, mmap_event->min);perf_output_put (&handle, mmap_event->ino);perf_output_put (&handle, mmap_event->ino_generation); +perf_output_put (&handle, mmap_event->prot); +perf_output_put (&handle, mmap_event->flags); } __output_copy(&handle, mmap_event->file_name,
@@ -5193,6 +5199,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)struct file *file = vma->vm_file;int maj =0 , min =0 ;u64 ino =0 , gen =0 ; +u32 prot =0 , flags =0 ;unsigned int size;char tmp[16 ];char *buf =NULL ;
@@ -5223,6 +5230,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) gen = inode->i_generation; maj =MAJOR (dev); min =MINOR (dev); + +if (vma->vm_flags &VM_READ ) + prot |=PROT_READ ; +if (vma->vm_flags &VM_WRITE ) + prot |=PROT_WRITE ; +if (vma->vm_flags &VM_EXEC ) + prot |=PROT_EXEC ; + +if (vma->vm_flags &VM_MAYSHARE ) + flags =MAP_SHARED ; +else + flags =MAP_PRIVATE ; + +if (vma->vm_flags &VM_DENYWRITE ) + flags |=MAP_DENYWRITE ; +if (vma->vm_flags &VM_MAYEXEC ) + flags |=MAP_EXECUTABLE ; +if (vma->vm_flags &VM_LOCKED ) + flags |=MAP_LOCKED ; +if (vma->vm_flags &VM_HUGETLB ) + flags |=MAP_HUGETLB ; + goto got_name; }else { name = (char *)arch_vma_name (vma);
@@ -5263,6 +5292,8 @@ got_name: mmap_event->min = min; mmap_event->ino = ino; mmap_event->ino_generation = gen; + mmap_event->prot = prot; + mmap_event->flags = flags;if (!(vma->vm_flags &VM_EXEC )) mmap_event->event_id.header.misc |=PERF_RECORD_MISC_MMAP_DATA ;
@@ -5303,6 +5334,8 @@ void perf_event_mmap(struct vm_area_struct *vma)/* .min (attr_mmap2 only) */ /* .ino (attr_mmap2 only) */ /* .ino_generation (attr_mmap2 only) */ +/* .prot (attr_mmap2 only) */ +/* .flags (attr_mmap2 only) */ };perf_event_mmap_event (&mmap_event);
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 2/9 Revert "perf: Disable PERF_RECORD_MMAP2 support"
In reply to Jiri OlsaFrom: Don Zickus <[email protected]>
This reverts commit 3090ffb5a2515990182f3f55b0688a7817325488.
Re-enable the mmap2 interface as we will have a user soon.
Since things have changed since perf disabled mmap2, small tweaks to the revert had to be done:
o commit 9d4ecc88 forced (n!=8) to become (n<7)
o a new libunwind test needed updating to use mmap2 interface
--- kernel/events/core.c | 4 ---- tools/perf/tests/dwarf-unwind.c | 2 +- tools/perf/util/event.c | 36 +++++++++++++++++++----------------- tools/perf/util/evsel.c | 1 + 4 files changed, 21 insertions(+), 22 deletions(-)
kernel/events/core.c +0 -4
@@ -6909,10 +6909,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,if (ret)return -EFAULT ; -/* disabled for now */ -if (attr->mmap2) -return -EINVAL ; -if (attr->__reserved_1)return -EINVAL ;
tools/perf/tests/dwarf-unwind.c +1 -1
@@ -15,7 +15,7 @@ static int mmap_handler(struct perf_tool *tool __maybe_unused,struct perf_sample *sample__maybe_unused , struct machine *machine) { - return machine__process_mmap_event(machine, event, NULL); + return machine__process_mmap2_event(machine, event, NULL); }static int init_live_machine (struct machine *machine)
tools/perf/util/event.c +19 -17
@@ -178,13 +178,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,return -1 ; } - event->header.type =PERF_RECORD_MMAP ; + event->header.type =PERF_RECORD_MMAP2 ;while (1 ) {char bf[BUFSIZ ];char prot[5 ];char execname[PATH_MAX ];char anonstr[] ="//anon" ; +unsigned int ino;size_t size;ssize_t n;
@@ -195,14 +196,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,strcpy (execname,"" );/* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ - n =sscanf (bf,"%" PRIx64"-%" PRIx64" %s %" PRIx64" %*x:%*x %*u %s\n" , - &event->mmap.start, &event->mmap.len, prot, - &event->mmap.pgoff, - execname); -/* -* Anon maps don't have the execname. -*/ -if (n <4 ) + n =sscanf (bf,"%" PRIx64"-%" PRIx64" %s %" PRIx64" %x:%x %u %s\n" , + &event->mmap2.start, &event->mmap2.len, prot, + &event->mmap2.pgoff, &event->mmap2.maj, + &event->mmap2.min, + &ino, execname); + + event->mmap2.ino = (u64 )ino; + +if (n <7 )continue ;/* * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
@@ -223,15 +225,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,strcpy (execname, anonstr); size =strlen (execname) +1 ; -memcpy (event->mmap.filename, execname, size); +memcpy (event->mmap2.filename, execname, size); size =PERF_ALIGN (size,sizeof (u64)); - event->mmap.len -= event->mmap.start; - event->mmap.header.size = (sizeof (event->mmap) - - (sizeof (event->mmap.filename) - size)); -memset (event->mmap.filename + size,0 , machine->id_hdr_size); - event->mmap.header.size += machine->id_hdr_size; - event->mmap.pid = tgid; - event->mmap.tid = pid; + event->mmap2.len -= event->mmap.start; + event->mmap2.header.size = (sizeof (event->mmap2) - + (sizeof (event->mmap2.filename) - size)); +memset (event->mmap2.filename + size,0 , machine->id_hdr_size); + event->mmap2.header.size += machine->id_hdr_size; + event->mmap2.pid = tgid; + event->mmap2.tid = pid;if (process (tool, event, &synth_sample, machine) !=0 ) { rc =-1 ;
tools/perf/util/evsel.c +1 -0
@@ -659,6 +659,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)perf_evsel__set_sample_bit (evsel,WEIGHT ); attr->mmap = track; + attr->mmap2 = track && !perf_missing_features.mmap2; attr->comm = track;if (opts->sample_transaction)
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 3/9 perf tools: Update mmap2 interface with protection and flag bits
In reply to Jiri OlsaFrom: Don Zickus <[email protected]>
The kernel piece passes more info now. Update the perf tool to reflect that and adjust the synthesized maps to play along.
--- tools/perf/util/event.c | 23 +++++++++++++++++++++-- tools/perf/util/event.h | 2 ++ tools/perf/util/machine.c | 4 +++- tools/perf/util/map.c | 4 +++- tools/perf/util/map.h | 4 +++- 5 files changed, 32 insertions(+), 5 deletions(-)
tools/perf/util/event.c +21 -2
@@ -1,4 +1,5 @@#include <linux/types.h> +#include <sys/mman.h> #include "event.h" #include "debug.h" #include "hist.h"
@@ -214,6 +215,21 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,else event->header.misc =PERF_RECORD_MISC_GUEST_USER ; +/* map protection and flags bits */ + event->mmap2.prot =0 ; + event->mmap2.flags =0 ; +if (prot[0 ] =='r' ) + event->mmap2.prot |=PROT_READ ; +if (prot[1 ] =='w' ) + event->mmap2.prot |=PROT_WRITE ; +if (prot[2 ] =='x' ) + event->mmap2.prot |=PROT_EXEC ; + +if (prot[3 ] =='s' ) + event->mmap2.flags |=MAP_SHARED ; +else + event->mmap2.flags |=MAP_PRIVATE ; +if (prot[2 ] !='x' ) {if (!mmap_data || prot[0 ] !='r' )continue ;
@@ -614,12 +630,15 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)size_t perf_event__fprintf_mmap2 (union perf_event *event,FILE *fp) {return fprintf (fp," %d/%d: [%#" PRIx64"(%#" PRIx64") @ %#" PRIx64 -" %02x:%02x %" PRIu64" %" PRIu64"]: %c %s\n" , +" %02x:%02x %" PRIu64" %" PRIu64"]: %c%c%c%c %s\n" , event->mmap2.pid, event->mmap2.tid, event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, event->mmap2.ino_generation, - (event->header.misc &PERF_RECORD_MISC_MMAP_DATA ) ?'r' :'x' , + (event->mmap2.prot &PROT_READ ) ?'r' :'-' , + (event->mmap2.prot &PROT_WRITE ) ?'w' :'-' , + (event->mmap2.prot &PROT_EXEC ) ?'x' :'-' , + (event->mmap2.flags &MAP_SHARED ) ?'s' :'p' , event->mmap2.filename); }
tools/perf/util/event.h +2 -0
@@ -27,6 +27,8 @@ struct mmap2_event {u32 min;u64 ino;u64 ino_generation; +u32 prot; +u32 flags;char filename[PATH_MAX ]; };
tools/perf/util/machine.c +3 -1
@@ -1060,6 +1060,8 @@ int machine__process_mmap2_event(struct machine *machine, event->mmap2.pid, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, event->mmap2.ino_generation, + event->mmap2.prot, + event->mmap2.flags, event->mmap2.filename, type);if (map ==NULL )
@@ -1105,7 +1107,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event map =map__new (&machine->user_dsos, event->mmap.start, event->mmap.len, event->mmap.pgoff, - event->mmap.pid,0 ,0 ,0 ,0 , + event->mmap.pid,0 ,0 ,0 ,0 ,0 ,0 , event->mmap.filename, type);
tools/perf/util/map.c +3 -1
@@ -138,7 +138,7 @@ void map__init(struct map *map, enum map_type type,struct map *map__new (struct list_head *dsos__list,u64 start,u64 len,u64 pgoff,u32 pid,u32 d_maj,u32 d_min,u64 ino, -u64 ino_gen,char *filename, +u64 ino_gen,u32 prot,u32 flags,char *filename,enum map_type type) {struct map *map =malloc (sizeof (*map));
@@ -157,6 +157,8 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, map->min = d_min; map->ino = ino; map->ino_generation = ino_gen; + map->prot = prot; + map->flags = flags;if ((anon || no_dso) && type ==MAP__FUNCTION ) {snprintf (newfilename,sizeof (newfilename),"/tmp/perf-%d.map" , pid);
tools/perf/util/map.h +3 -1
@@ -35,6 +35,8 @@ struct map {bool referenced;bool erange_warned;u32 priv; +u32 prot; +u32 flags;u64 pgoff;u64 reloc;u32 maj, min;/* only valid for MMAP2 record */
@@ -118,7 +120,7 @@ void map__init(struct map *map, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso);struct map *map__new (struct list_head *dsos__list,u64 start,u64 len,u64 pgoff,u32 pid,u32 d_maj,u32 d_min,u64 ino, -u64 ino_gen, +u64 ino_gen,u32 prot,u32 flags,char *filename,enum map_type type);struct map *map__new2 (u64 start,struct dso *dso,enum map_type type);void map__delete (struct map *map);
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 4/9 perf report: Add mem-mode documentation to report command
In reply to Jiri OlsaFrom: Don Zickus <[email protected]>
Add mem-mode sorting types and mem-mode itself to perf-report documentation.
--- tools/perf/Documentation/perf-report.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
tools/perf/Documentation/perf-report.txt +22 -0
@@ -117,6 +117,21 @@ OPTIONS By default, every sort keys not specified in -F will be appended automatically. + If --mem-mode option is used, following sort keys are also available + (incompatible with --branch-stack): + symbol_daddr, dso_daddr, locked, tlb, mem, snoop. + + - symbol_daddr: name of data symbol being executed on at the time of sample + - dso_daddr: name of library or module containing the data being executed + on at the time of sample + - locked: whether the bus was locked at the time of sample + - tlb: type of tlb access for the data at the time of sample + - mem: type of memory access for the data at the time of sample + - snoop: type of snoop (if any) for the data at the time of sample + + And default sort keys are changed to local_weight, mem, sym, dso, + symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. + -p:: --parent=<regex>:: A regex filter to identify parent. The parent is a caller of this
@@ -255,6 +270,13 @@ OPTIONS Demangle symbol names to human readable form. It's enabled by default, disable with --no-demangle. +--mem-mode:: + Use the data addresses of samples in addition to instruction addresses + to build the histograms. To generate meaningful output, the perf.data + file must have been obtained using perf record -d -W and using a + special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See + 'perf mem' for simpler access. + --percent-limit:: Do not show entries which have an overhead under that percent. (Default: 0).
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 5/9 perf trace: Warn the user when not available
In reply to Jiri OlsaFrom: Arnaldo Carvalho de Melo <[email protected]>
When the audit-libs devel package is not found at build time we disable the 'trace' command, as we are not able to map syscall numbers to strings, but then the message the user is presented is cryptic:
[root@zoo linux]# trace ls
perf: 'ls' is not a perf-command. See 'perf --help'.
Fix it by presenting a more helpful message:
[root@zoo linux]# trace l
trace command not available: missing audit-libs devel package at build time.
--- tools/perf/perf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/perf/perf.c +6 -2
@@ -481,14 +481,18 @@ int main(int argc, const char **argv)fprintf (stderr,"cannot handle %s internally" , cmd); goto out; } -#ifdef HAVE_LIBAUDIT_SUPPORT if (!prefixcmp (cmd,"trace" )) { +#ifdef HAVE_LIBAUDIT_SUPPORT set_buildid_dir ();setup_path (); argv[0 ] ="trace" ;return cmd_trace (argc, argv,NULL ); - } +#else +fprintf (stderr, +"trace command not available: missing audit-libs devel package at build time.\n" ); + goto out;#endif + }/* Look for flags.. */ argv++; argc--;
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 6/9 perf tools: Add warning when disabling perl scripting support due to missing devel files
In reply to Jiri OlsaFrom: Arnaldo Carvalho de Melo <[email protected]>
We were just showing "libperl: OFF", unlike other features where we present the user with a message helping have a feature built in.
Fix it by adding the following message:
config/Makefile:450: Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed
--- tools/perf/config/Makefile | 1 + 1 file changed, 1 insertion(+)
tools/perf/config/Makefile +1 -0
@@ -447,6 +447,7 @@ else ifneq ($(feature-libperl), 1) CFLAGS += -DNO_LIBPERL NO_LIBPERL := 1 + msg := $(warning Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed); else LDFLAGS += $(PERL_EMBED_LDFLAGS) EXTLIBS += $(PERL_EMBED_LIBADD)
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 7/9 perf tools: Consider header files outside perf directory in tags target
In reply to Jiri OlsaFrom: Sebastian Andrzej Siewior <[email protected]>
This fixes lookups like "vi -t event_format"
--- tools/perf/Makefile.perf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
tools/perf/Makefile.perf +6 -3
@@ -814,17 +814,20 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html $(DOC_TARGETS): $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) +TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol +TAG_FILES= ../../include/uapi/linux/perf_event.h + TAGS: $(RM) TAGS - $(FIND) . -name '*.[hcS]' -print | xargs etags -a + $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES) tags: $(RM) tags - $(FIND) . -name '*.[hcS]' -print | xargs ctags -a + $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES) cscope: $(RM) cscope* - $(FIND) . -name '*.[hcS]' -print | xargs cscope -b + $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) ### Detect prefix changes TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 8/9 perf tools: Allow overriding sysfs and proc finding with env var
In reply to Jiri OlsaFrom: Cody P Schafer <[email protected]>
SYSFS_PATH and PROC_PATH environment variables now let the user override the detection of sysfs and proc locations for testing purposes.
--- tools/lib/api/fs/fs.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-)
tools/lib/api/fs/fs.c +42 -1
@@ -1,8 +1,10 @@/* TODO merge/factor in debugfs.c here */ +#include <ctype.h> #include <errno.h> #include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/vfs.h>
@@ -96,12 +98,51 @@ static bool fs__check_mounts(struct fs *fs)return false; } +static void mem_toupper (char *f,size_t len) +{ +while (len) { + *f =toupper (*f); + f++; + len--; + } +} + +/* +* Check for "NAME_PATH" environment variable to override fs location (for +* testing). This matches the recommendation in Documentation/sysfs-rules.txt +* for SYSFS_PATH. +*/ +static bool fs__env_override (struct fs *fs) +{ +char *override_path; +size_t name_len =strlen (fs->name); +/* name + "_PATH" + '\0' */ +char upper_name[name_len +5 +1 ]; +memcpy (upper_name, fs->name, name_len); +mem_toupper (upper_name, name_len); +strcpy (&upper_name[name_len],"_PATH" ); + + override_path =getenv (upper_name); +if (!override_path) +return false; + + fs->found = true; +strncpy (fs->path, override_path,sizeof (fs->path)); +return true; +} +static const char *fs__get_mountpoint (struct fs *fs) { +if (fs__env_override (fs)) +return fs->path; +if (fs__check_mounts (fs))return fs->path; -return fs__read_mounts (fs) ? fs->path :NULL ; +if (fs__read_mounts (fs)) +return fs->path; + +return NULL ; }static const char *fs__mountpoint (int idx)
Signature · 1 line
1.8.3.1
Jiri Olsa
reviewerPATCH 9/9 tools lib traceevent: Added support for __get_bitmask() macro
In reply to Jiri OlsaFrom: "Steven Rostedt (Red Hat)" <[email protected]>
Coming in v3.16, trace events will be able to save bitmasks in raw format in the ring buffer and output it with the __get_bitmask() macro.
In order for userspace tools to parse this, it must be able to handle the __get_bitmask() call and be able to convert the data that's in the ring buffer into a nice bitmask format. The output is similar to what the kernel uses to print bitmasks, with a comma separator every 4 bytes (8 characters).
This allows for cpumasks to also be saved efficiently.
The first user is the thermal:thermal_power_limit event which has the following output:
thermal_power_limit: cpus=0000000f freq=1900000 cdev_state=0 power=5252
--- tools/lib/traceevent/event-parse.c | 113 +++++++++++++++++++++ tools/lib/traceevent/event-parse.h | 7 ++ .../perf/util/scripting-engines/trace-event-perl.c | 1 + .../util/scripting-engines/trace-event-python.c | 1 + 4 files changed, 122 insertions(+)
tools/lib/traceevent/event-parse.c +113 -0
@@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg)case PRINT_BSTRING :free (arg->string.string);break ; +case PRINT_BITMASK : +free (arg->bitmask.bitmask); +break ;case PRINT_DYNAMIC_ARRAY :free (arg->dynarray.index);break ;
@@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val) case PRINT_FIELD ... PRINT_SYMBOL:case PRINT_STRING :case PRINT_BSTRING : +case PRINT_BITMASK :default :do_warning ("invalid eval type %d" , arg->type); ret =0 ;
@@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg) case PRINT_FIELD ... PRINT_SYMBOL:case PRINT_STRING :case PRINT_BSTRING : +case PRINT_BITMASK :default :do_warning ("invalid eval type %d" , arg->type);break ;
@@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg,return EVENT_ERROR ; } +static enum event_type +process_bitmask (struct event_format *event__maybe_unused ,struct print_arg *arg, +char **tok) +{ +enum event_type type; +char *token; + +if (read_expect_type (EVENT_ITEM , &token) <0 ) + goto out_free; + + arg->type =PRINT_BITMASK ; + arg->bitmask.bitmask = token; + arg->bitmask.offset =-1 ; + +if (read_expected (EVENT_DELIM ,")" ) <0 ) + goto out_err; + + type =read_token (&token); + *tok = token; + +return type; + + out_free: +free_token (token); + out_err: + *tok =NULL ; +return EVENT_ERROR ; +} +static struct pevent_function_handler *find_func_handler (struct pevent *pevent,char *func_name) {
@@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg,free_token (token);return process_str (event, arg, tok); } +if (strcmp (token,"__get_bitmask" ) ==0 ) { +free_token (token); +return process_bitmask (event, arg, tok); + }if (strcmp (token,"__get_dynamic_array" ) ==0 ) {free_token (token);return process_dynamic_array (event, arg, tok);
@@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_argreturn eval_type (val, arg,0 );case PRINT_STRING :case PRINT_BSTRING : +case PRINT_BITMASK :return 0 ;case PRINT_FUNC : {struct trace_seq s;
@@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format,trace_seq_printf (s, format, str); } +static void print_bitmask_to_seq (struct pevent *pevent, +struct trace_seq *s,const char *format, +int len_arg,const void *data,int size) +{ +int nr_bits = size *8 ; +int str_size = (nr_bits +3 ) /4 ; +int len =0 ; +char buf[3 ]; +char *str; +int index; +int i; + +/* +* The kernel likes to put in commas every 32 bits, we +* can do the same. +*/ + str_size += (nr_bits -1 ) /32 ; + + str =malloc (str_size +1 ); +if (!str) { +do_warning ("%s: not enough memory!" , __func__); +return ; + } + str[str_size] =0 ; + +/* Start out with -2 for the two chars per byte */ +for (i = str_size -2 ; i >=0 ; i -=2 ) { +/* +* data points to a bit mask of size bytes. +* In the kernel, this is an array of long words, thus +* endianess is very important. +*/ +if (pevent->file_bigendian) + index = size - (len +1 ); +else + index = len; + +snprintf (buf,3 ,"%02x" , *((unsigned char *)data + index)); +memcpy (str + i, buf,2 ); + len++; +if (!(len &3 ) && i >0 ) { + i--; + str[i] =',' ; + } + } + +if (len_arg >=0 ) +trace_seq_printf (s, format, len_arg, str); +else +trace_seq_printf (s, format, str); + +free (str); +} +static void print_str_arg (struct trace_seq *s,void *data,int size,struct event_format *event,const char *format,int len_arg,struct print_arg *arg)
@@ -3691,6 +3784,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,case PRINT_BSTRING :print_str_to_seq (s, format, len_arg, arg->string.string);break ; +case PRINT_BITMASK : { +int bitmask_offset; +int bitmask_size; + +if (arg->bitmask.offset ==-1 ) { +struct format_field *f; + + f =pevent_find_any_field (event, arg->bitmask.bitmask); + arg->bitmask.offset = f->offset; + } + bitmask_offset =data2host4 (pevent, data + arg->string.offset); + bitmask_size = bitmask_offset >>16 ; + bitmask_offset &=0xffff ; +print_bitmask_to_seq (pevent, s, format, len_arg, + data + bitmask_offset, bitmask_size); +break ; + }case PRINT_OP :/* * The only op for string should be ? :
@@ -4822,6 +4932,9 @@ static void print_args(struct print_arg *args)case PRINT_BSTRING :printf ("__get_str(%s)" , args->string.string);break ; +case PRINT_BITMASK : +printf ("__get_bitmask(%s)" , args->bitmask.bitmask); +break ;case PRINT_TYPE :printf ("(%s)" , args->typecast.type);print_args (args->typecast.item);
tools/lib/traceevent/event-parse.h +7 -0
@@ -208,6 +208,11 @@ struct print_arg_string {int offset; }; +struct print_arg_bitmask { +char *bitmask; +int offset; +}; +struct print_arg_field {char *name;struct format_field *field;
@@ -274,6 +279,7 @@ enum print_arg_type {PRINT_DYNAMIC_ARRAY ,PRINT_OP ,PRINT_FUNC , + PRINT_BITMASK, }; struct print_arg {
@@ -288,6 +294,7 @@ struct print_arg {struct print_arg_hex hex;struct print_arg_func func;struct print_arg_string string; +struct print_arg_bitmask bitmask;struct print_arg_op op;struct print_arg_dynarray dynarray; };
tools/perf/util/scripting-engines/trace-event-perl.c +1 -0
@@ -215,6 +215,7 @@ static void define_event_symbols(struct event_format *event,case PRINT_BSTRING :case PRINT_DYNAMIC_ARRAY :case PRINT_STRING : +case PRINT_BITMASK :break ;case PRINT_TYPE :define_event_symbols (event, ev_name, args->typecast.item);
tools/perf/util/scripting-engines/trace-event-python.c +1 -0
@@ -197,6 +197,7 @@ static void define_event_symbols(struct event_format *event,case PRINT_BSTRING :case PRINT_DYNAMIC_ARRAY :case PRINT_FUNC : +case PRINT_BITMASK :/* we should warn... */ return ; }
Signature · 1 line
1.8.3.1