diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-10 10:33:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-10 10:33:58 -0700 |
commit | c48ce9f190266b763e809dd79fcf4152f558793c (patch) | |
tree | 60490f3c5ae8e236dc6ea336ca9c695527c835f5 /tools/perf/pmu-events/json.c | |
parent | 84ed2da02f4cda6759880c87a213ee80c91ca3bd (diff) | |
parent | c68306ce20ad03ce655a367fc33ad06e12bb87a6 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf tooling updates from Thomas Gleixner:
- handle uretprobe placement proper on little endian PPC64
- fix buffer handling in libtraceevent
- add a missing pointer derefence in perf probe
- fix the build of host tools in cross builds
- fix Intel PT timestamp handling
- synchronize memcpy, cpufeatures and bpf headers with the kernel headers
- support for vendor supplied JSON files describing PMU events
- a new set of tool tips
- initial work for clang/llvm support
- address some style issues found by cppcheck
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (35 commits)
tools build: Add feature detection for g++
tools build: Support compiling C++ source file
perf top/report: Add tips about a list option
perf report/top: Add a tip about system-wide collection from all CPUs
perf report/top: Add a tip about source line numbers with overhead
tools: Synchronize tools/include/uapi/linux/bpf.h
tools: Synchronize tools/arch/x86/include/asm/cpufeatures.h
perf bench mem: Sync memcpy assembly sources with the kernel
perf jevents: Fix Intel JSON fixed counter conversions
tools lib traceevent: Fix kbuffer_read_at_offset()
perf intel-pt: Fix MTC timestamp calculation for large MTC periods
perf intel-pt: Fix estimated timestamps for cycle-accurate mode
perf uretprobe ppc64le: Fix probe location
perf pmu-events: Add Skylake frontend MSR support
perf pmu-events: Fix fixed counters on Intel
perf tools: Make alias matching case-insensitive
perf tools: Allow period= in perf stat CPU event descriptions.
perf tools: Add README for info on parsing JSON/map files
perf list jevents: Add support for event list topics
perf list: Support long jevents descriptions
...
Diffstat (limited to 'tools/perf/pmu-events/json.c')
-rw-r--r-- | tools/perf/pmu-events/json.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/tools/perf/pmu-events/json.c b/tools/perf/pmu-events/json.c new file mode 100644 index 000000000000..f67bbb0aa36e --- /dev/null +++ b/tools/perf/pmu-events/json.c @@ -0,0 +1,162 @@ +/* Parse JSON files using the JSMN parser. */ + +/* + * Copyright (c) 2014, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include "jsmn.h" +#include "json.h" +#include <linux/kernel.h> + + +static char *mapfile(const char *fn, size_t *size) +{ + unsigned ps = sysconf(_SC_PAGESIZE); + struct stat st; + char *map = NULL; + int err; + int fd = open(fn, O_RDONLY); + + if (fd < 0 && verbose && fn) { + pr_err("Error opening events file '%s': %s\n", fn, + strerror(errno)); + } + + if (fd < 0) + return NULL; + err = fstat(fd, &st); + if (err < 0) + goto out; + *size = st.st_size; + map = mmap(NULL, + (st.st_size + ps - 1) & ~(ps - 1), + PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) + map = NULL; +out: + close(fd); + return map; +} + +static void unmapfile(char *map, size_t size) +{ + unsigned ps = sysconf(_SC_PAGESIZE); + munmap(map, roundup(size, ps)); +} + +/* + * Parse json file using jsmn. Return array of tokens, + * and mapped file. Caller needs to free array. + */ +jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len) +{ + jsmn_parser parser; + jsmntok_t *tokens; + jsmnerr_t res; + unsigned sz; + + *map = mapfile(fn, size); + if (!*map) + return NULL; + /* Heuristic */ + sz = *size * 16; + tokens = malloc(sz); + if (!tokens) + goto error; + jsmn_init(&parser); + res = jsmn_parse(&parser, *map, *size, tokens, + sz / sizeof(jsmntok_t)); + if (res != JSMN_SUCCESS) { + pr_err("%s: json error %s\n", fn, jsmn_strerror(res)); + goto error_free; + } + if (len) + *len = parser.toknext; + return tokens; +error_free: + free(tokens); +error: + unmapfile(*map, *size); + return NULL; +} + +void free_json(char *map, size_t size, jsmntok_t *tokens) +{ + free(tokens); + unmapfile(map, size); +} + +static int countchar(char *map, char c, int end) +{ + int i; + int count = 0; + for (i = 0; i < end; i++) + if (map[i] == c) + count++; + return count; +} + +/* Return line number of a jsmn token */ +int json_line(char *map, jsmntok_t *t) +{ + return countchar(map, '\n', t->start) + 1; +} + +static const char * const jsmn_types[] = { + [JSMN_PRIMITIVE] = "primitive", + [JSMN_ARRAY] = "array", + [JSMN_OBJECT] = "object", + [JSMN_STRING] = "string" +}; + +#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?") + +/* Return type name of a jsmn token */ +const char *json_name(jsmntok_t *t) +{ + return LOOKUP(jsmn_types, t->type); +} + +int json_len(jsmntok_t *t) +{ + return t->end - t->start; +} + +/* Is string t equal to s? */ +int json_streq(char *map, jsmntok_t *t, const char *s) +{ + unsigned len = json_len(t); + return len == strlen(s) && !strncasecmp(map + t->start, s, len); +} |