Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Mark events as (x86 only) in help output for 'perf kvm stat live" (Alexander Yarygin) - Provide a better explanation when mmap fails in 'trace' (Arnaldo Carvalho de Melo) - Add --buildid-dir option to set cache directory, i.e. use: $ perf --buildid-dir /path/to/dir tool --tool-options (Jiri Olsa) - Fix memcpy/memset 'perf bench' output (Rabin Vicent) - Fix 'perf test' attr tests size values to cope with machine state on interrupt ABI changes (Jiri Olsa) - Fixup callchain type parameter handling error message (Kan Liang) Infrastructure changes and cleanups: - calloc/xcalloc: Fix argument order (Arjun Sreedharan) - Move filename__read_int from tools/perf/ to tools/lib, add sysctl__read_int there and use it in place of ad-hoc copies (Arnaldo Carvalho de Melo) - Use single strcmp call instead of two (Jiri Olsa) - Remove extra debugdir variables in 'perf buildid-cache' (Jiri Olsa) - Fix -a segfault related to kcore handling in 'perf buildid-cache' (Jiri Olsa) - Move cpumode resolve code to add_callchain_ip (Kan Liang) - Merge memset into memcpy 'perf bench' (Rabin Vincent) - Change print format from %lu to %PRIu64 in the hists browser (Tom Huynh)
Unified · Split
| @@ -330,10 +330,10 @@ static void set_subtitle(void) · 329 unmodified lines | ||
| 330 | 330 | list_for_each_entry(sp, &trail, entries) { |
| 331 | 331 | if (sp->text) { |
| 332 | 332 | if (pos) { |
| 333 | − pos->next = xcalloc(sizeof(*pos), 1); | |
| 333 | + pos->next = xcalloc(1, sizeof(*pos)); | |
| 334 | 334 | pos = pos->next; |
| 335 | 335 | } else { |
| 336 | − subtitles = pos = xcalloc(sizeof(*pos), 1); | |
| 336 | + subtitles = pos = xcalloc(1, sizeof(*pos)); | |
| 337 | 337 | } |
| 338 | 338 | pos->text = sp->text; |
| 339 | 339 | } |
| @@ -7,6 +7,10 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <stdlib.h> |
| 8 | 8 | #include <string.h> |
| 9 | 9 | #include <sys/vfs.h> |
| 10 | +#include <sys/types.h> | |
| 11 | +#include <sys/stat.h> | |
| 12 | +#include <fcntl.h> | |
| 13 | +#include <unistd.h> | |
| 10 | 14 | |
| 11 | 15 | #include "debugfs.h" |
| 12 | 16 | #include "fs.h" |
| @@ -163,3 +167,33 @@ const char *name##__mountpoint(void) \ · 150 unmodified lines | ||
| 163 | 167 | |
| 164 | 168 | FS__MOUNTPOINT(sysfs, FS__SYSFS); |
| 165 | 169 | FS__MOUNTPOINT(procfs, FS__PROCFS); |
| 170 | + | |
| 171 | +int filename__read_int(const char *filename, int *value) | |
| 172 | +{ | |
| 173 | + char line[64]; | |
| 174 | + int fd = open(filename, O_RDONLY), err = -1; | |
| 175 | + | |
| 176 | + if (fd < 0) | |
| 177 | + return -1; | |
| 178 | + | |
| 179 | + if (read(fd, line, sizeof(line)) > 0) { | |
| 180 | + *value = atoi(line); | |
| 181 | + err = 0; | |
| 182 | + } | |
| 183 | + | |
| 184 | + close(fd); | |
| 185 | + return err; | |
| 186 | +} | |
| 187 | + | |
| 188 | +int sysctl__read_int(const char *sysctl, int *value) | |
| 189 | +{ | |
| 190 | + char path[PATH_MAX]; | |
| 191 | + const char *procfs = procfs__mountpoint(); | |
| 192 | + | |
| 193 | + if (!procfs) | |
| 194 | + return -1; | |
| 195 | + | |
| 196 | + snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl); | |
| 197 | + | |
| 198 | + return filename__read_int(path, value); | |
| 199 | +} | |
| @@ -11,4 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | const char *sysfs__mountpoint(void); |
| 13 | 13 | const char *procfs__mountpoint(void); |
| 14 | + | |
| 15 | +int filename__read_int(const char *filename, int *value); | |
| 16 | +int sysctl__read_int(const char *sysctl, int *value); | |
| 14 | 17 | #endif /* __API_FS__ */ |
| @@ -18,6 +18,10 @@ OPTIONS · 17 unmodified lines | ||
| 18 | 18 | --debug verbose # sets verbose = 1 |
| 19 | 19 | --debug verbose=2 # sets verbose = 2 |
| 20 | 20 | |
| 21 | +--buildid-dir:: | |
| 22 | + Setup buildid cache directory. It has higher priority than | |
| 23 | + buildid.dir config file option. | |
| 24 | + | |
| 21 | 25 | DESCRIPTION |
| 22 | 26 | ----------- |
| 23 | 27 | Performance counters for Linux are a new kernel-based subsystem |
| @@ -458,7 +458,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o · 457 unmodified lines | ||
| 458 | 458 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o |
| 459 | 459 | endif |
| 460 | 460 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
| 461 | −BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o | |
| 462 | 461 | BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o |
| 463 | 462 | BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o |
| 464 | 463 | BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "../util/cloexec.h" |
| 14 | 14 | #include "bench.h" |
| 15 | 15 | #include "mem-memcpy-arch.h" |
| 16 | +#include "mem-memset-arch.h" | |
| 16 | 17 | |
| 17 | 18 | #include <stdio.h> |
| 18 | 19 | #include <stdlib.h> |
| @@ -48,20 +49,24 @@ static const struct option options[] = { · 29 unmodified lines | ||
| 48 | 49 | }; |
| 49 | 50 | |
| 50 | 51 | typedef void *(*memcpy_t)(void *, const void *, size_t); |
| 52 | +typedef void *(*memset_t)(void *, int, size_t); | |
| 51 | 53 | |
| 52 | 54 | struct routine { |
| 53 | 55 | const char *name; |
| 54 | 56 | const char *desc; |
| 55 | − memcpy_t fn; | |
| 57 | + union { | |
| 58 | + memcpy_t memcpy; | |
| 59 | + memset_t memset; | |
| 60 | + } fn; | |
| 56 | 61 | }; |
| 57 | 62 | |
| 58 | −struct routine routines[] = { | |
| 59 | − { "default", | |
| 60 | − "Default memcpy() provided by glibc", | |
| 61 | − memcpy }, | |
| 63 | +struct routine memcpy_routines[] = { | |
| 64 | + { .name = "default", | |
| 65 | + .desc = "Default memcpy() provided by glibc", | |
| 66 | + .fn.memcpy = memcpy }, | |
| 62 | 67 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
| 63 | 68 | |
| 64 | −#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, | |
| 69 | +#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, | |
| 65 | 70 | #include "mem-memcpy-x86-64-asm-def.h" |
| 66 | 71 | #undef MEMCPY_FN |
| 67 | 72 | |
| @@ -69,7 +74,7 @@ struct routine routines[] = { · 1 unmodified line | ||
| 69 | 74 | |
| 70 | 75 | { NULL, |
| 71 | 76 | NULL, |
| 72 | − NULL } | |
| 77 | + {NULL} } | |
| 73 | 78 | }; |
| 74 | 79 | |
| 75 | 80 | static const char * const bench_mem_memcpy_usage[] = { |
| @@ -110,63 +115,6 @@ static double timeval2double(struct timeval *ts) · 34 unmodified lines | ||
| 110 | 115 | (double)ts->tv_usec / (double)1000000; |
| 111 | 116 | } |
| 112 | 117 | |
| 113 | −static void alloc_mem(void **dst, void **src, size_t length) | |
| 114 | −{ | |
| 115 | − *dst = zalloc(length); | |
| 116 | − if (!*dst) | |
| 117 | − die("memory allocation failed - maybe length is too large?\n"); | |
| 118 | − | |
| 119 | − *src = zalloc(length); | |
| 120 | − if (!*src) | |
| 121 | − die("memory allocation failed - maybe length is too large?\n"); | |
| 122 | − /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ | |
| 123 | − memset(*src, 0, length); | |
| 124 | −} | |
| 125 | − | |
| 126 | −static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) | |
| 127 | −{ | |
| 128 | − u64 cycle_start = 0ULL, cycle_end = 0ULL; | |
| 129 | − void *src = NULL, *dst = NULL; | |
| 130 | − int i; | |
| 131 | − | |
| 132 | − alloc_mem(&src, &dst, len); | |
| 133 | − | |
| 134 | − if (prefault) | |
| 135 | − fn(dst, src, len); | |
| 136 | − | |
| 137 | − cycle_start = get_cycle(); | |
| 138 | − for (i = 0; i < iterations; ++i) | |
| 139 | − fn(dst, src, len); | |
| 140 | − cycle_end = get_cycle(); | |
| 141 | − | |
| 142 | − free(src); | |
| 143 | − free(dst); | |
| 144 | − return cycle_end - cycle_start; | |
| 145 | −} | |
| 146 | − | |
| 147 | −static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) | |
| 148 | −{ | |
| 149 | − struct timeval tv_start, tv_end, tv_diff; | |
| 150 | − void *src = NULL, *dst = NULL; | |
| 151 | − int i; | |
| 152 | − | |
| 153 | − alloc_mem(&src, &dst, len); | |
| 154 | − | |
| 155 | − if (prefault) | |
| 156 | − fn(dst, src, len); | |
| 157 | − | |
| 158 | − BUG_ON(gettimeofday(&tv_start, NULL)); | |
| 159 | − for (i = 0; i < iterations; ++i) | |
| 160 | − fn(dst, src, len); | |
| 161 | − BUG_ON(gettimeofday(&tv_end, NULL)); | |
| 162 | − | |
| 163 | − timersub(&tv_end, &tv_start, &tv_diff); | |
| 164 | − | |
| 165 | − free(src); | |
| 166 | − free(dst); | |
| 167 | − return (double)((double)len / timeval2double(&tv_diff)); | |
| 168 | −} | |
| 169 | − | |
| 170 | 118 | #define pf (no_prefault ? 0 : 1) |
| 171 | 119 | |
| 172 | 120 | #define print_bps(x) do { \ |
| @@ -180,16 +128,25 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) · 7 unmodified lines | ||
| 180 | 128 | printf(" %14lf GB/Sec", x / K / K / K); \ |
| 181 | 129 | } while (0) |
| 182 | 130 | |
| 183 | −int bench_mem_memcpy(int argc, const char **argv, | |
| 184 | − const char *prefix __maybe_unused) | |
| 131 | +struct bench_mem_info { | |
| 132 | + const struct routine *routines; | |
| 133 | + u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault); | |
| 134 | + double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault); | |
| 135 | + const char *const *usage; | |
| 136 | +}; | |
| 137 | + | |
| 138 | +static int bench_mem_common(int argc, const char **argv, | |
| 139 | + const char *prefix __maybe_unused, | |
| 140 | + struct bench_mem_info *info) | |
| 185 | 141 | { |
| 186 | 142 | int i; |
| 187 | 143 | size_t len; |
| 144 | + double totallen; | |
| 188 | 145 | double result_bps[2]; |
| 189 | 146 | u64 result_cycle[2]; |
| 190 | 147 | |
| 191 | 148 | argc = parse_options(argc, argv, options, |
| 192 | − bench_mem_memcpy_usage, 0); | |
| 149 | + info->usage, 0); | |
| 193 | 150 | |
| 194 | 151 | if (no_prefault && only_prefault) { |
| 195 | 152 | fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); |
| @@ -200,6 +157,7 @@ int bench_mem_memcpy(int argc, const char **argv, · 4 unmodified lines | ||
| 200 | 157 | init_cycle(); |
| 201 | 158 | |
| 202 | 159 | len = (size_t)perf_atoll((char *)length_str); |
| 160 | + totallen = (double)len * iterations; | |
| 203 | 161 | |
| 204 | 162 | result_cycle[0] = result_cycle[1] = 0ULL; |
| 205 | 163 | result_bps[0] = result_bps[1] = 0.0; |
| @@ -213,16 +171,16 @@ int bench_mem_memcpy(int argc, const char **argv, · 7 unmodified lines | ||
| 213 | 171 | if (only_prefault && no_prefault) |
| 214 | 172 | only_prefault = no_prefault = false; |
| 215 | 173 | |
| 216 | − for (i = 0; routines[i].name; i++) { | |
| 217 | − if (!strcmp(routines[i].name, routine)) | |
| 174 | + for (i = 0; info->routines[i].name; i++) { | |
| 175 | + if (!strcmp(info->routines[i].name, routine)) | |
| 218 | 176 | break; |
| 219 | 177 | } |
| 220 | − if (!routines[i].name) { | |
| 178 | + if (!info->routines[i].name) { | |
| 221 | 179 | printf("Unknown routine:%s\n", routine); |
| 222 | 180 | printf("Available routines...\n"); |
| 223 | − for (i = 0; routines[i].name; i++) { | |
| 181 | + for (i = 0; info->routines[i].name; i++) { | |
| 224 | 182 | printf("\t%s ... %s\n", |
| 225 | − routines[i].name, routines[i].desc); | |
| 183 | + info->routines[i].name, info->routines[i].desc); | |
| 226 | 184 | } |
| 227 | 185 | return 1; |
| 228 | 186 | } |
| @@ -234,25 +192,25 @@ int bench_mem_memcpy(int argc, const char **argv, · 5 unmodified lines | ||
| 234 | 192 | /* show both of results */ |
| 235 | 193 | if (use_cycle) { |
| 236 | 194 | result_cycle[0] = |
| 237 | − do_memcpy_cycle(routines[i].fn, len, false); | |
| 195 | + info->do_cycle(&info->routines[i], len, false); | |
| 238 | 196 | result_cycle[1] = |
| 239 | − do_memcpy_cycle(routines[i].fn, len, true); | |
| 197 | + info->do_cycle(&info->routines[i], len, true); | |
| 240 | 198 | } else { |
| 241 | 199 | result_bps[0] = |
| 242 | − do_memcpy_gettimeofday(routines[i].fn, | |
| 200 | + info->do_gettimeofday(&info->routines[i], | |
| 243 | 201 | len, false); |
| 244 | 202 | result_bps[1] = |
| 245 | − do_memcpy_gettimeofday(routines[i].fn, | |
| 203 | + info->do_gettimeofday(&info->routines[i], | |
| 246 | 204 | len, true); |
| 247 | 205 | } |
| 248 | 206 | } else { |
| 249 | 207 | if (use_cycle) { |
| 250 | 208 | result_cycle[pf] = |
| 251 | − do_memcpy_cycle(routines[i].fn, | |
| 209 | + info->do_cycle(&info->routines[i], | |
| 252 | 210 | len, only_prefault); |
| 253 | 211 | } else { |
| 254 | 212 | result_bps[pf] = |
| 255 | − do_memcpy_gettimeofday(routines[i].fn, | |
| 213 | + info->do_gettimeofday(&info->routines[i], | |
| 256 | 214 | len, only_prefault); |
| 257 | 215 | } |
| 258 | 216 | } |
| @@ -263,10 +221,10 @@ int bench_mem_memcpy(int argc, const char **argv, · 4 unmodified lines | ||
| 263 | 221 | if (use_cycle) { |
| 264 | 222 | printf(" %14lf Cycle/Byte\n", |
| 265 | 223 | (double)result_cycle[0] |
| 266 | − / (double)len); | |
| 224 | + / totallen); | |
| 267 | 225 | printf(" %14lf Cycle/Byte (with prefault)\n", |
| 268 | 226 | (double)result_cycle[1] |
| 269 | − / (double)len); | |
| 227 | + / totallen); | |
| 270 | 228 | } else { |
| 271 | 229 | print_bps(result_bps[0]); |
| 272 | 230 | printf("\n"); |
| @@ -277,7 +235,7 @@ int bench_mem_memcpy(int argc, const char **argv, · 4 unmodified lines | ||
| 277 | 235 | if (use_cycle) { |
| 278 | 236 | printf(" %14lf Cycle/Byte", |
| 279 | 237 | (double)result_cycle[pf] |
| 280 | − / (double)len); | |
| 238 | + / totallen); | |
| 281 | 239 | } else |
| 282 | 240 | print_bps(result_bps[pf]); |
| 283 | 241 | |
| @@ -288,8 +246,8 @@ int bench_mem_memcpy(int argc, const char **argv, · 4 unmodified lines | ||
| 288 | 246 | if (!only_prefault && !no_prefault) { |
| 289 | 247 | if (use_cycle) { |
| 290 | 248 | printf("%lf %lf\n", |
| 291 | − (double)result_cycle[0] / (double)len, | |
| 292 | − (double)result_cycle[1] / (double)len); | |
| 249 | + (double)result_cycle[0] / totallen, | |
| 250 | + (double)result_cycle[1] / totallen); | |
| 293 | 251 | } else { |
| 294 | 252 | printf("%lf %lf\n", |
| 295 | 253 | result_bps[0], result_bps[1]); |
| @@ -297,7 +255,7 @@ int bench_mem_memcpy(int argc, const char **argv, · 1 unmodified line | ||
| 297 | 255 | } else { |
| 298 | 256 | if (use_cycle) { |
| 299 | 257 | printf("%lf\n", (double)result_cycle[pf] |
| 300 | − / (double)len); | |
| 258 | + / totallen); | |
| 301 | 259 | } else |
| 302 | 260 | printf("%lf\n", result_bps[pf]); |
| 303 | 261 | } |
| @@ -310,3 +268,163 @@ int bench_mem_memcpy(int argc, const char **argv, · 6 unmodified lines | ||
| 310 | 268 | |
| 311 | 269 | return 0; |
| 312 | 270 | } |
| 271 | + | |
| 272 | +static void memcpy_alloc_mem(void **dst, void **src, size_t length) | |
| 273 | +{ | |
| 274 | + *dst = zalloc(length); | |
| 275 | + if (!*dst) | |
| 276 | + die("memory allocation failed - maybe length is too large?\n"); | |
| 277 | + | |
| 278 | + *src = zalloc(length); | |
| 279 | + if (!*src) | |
| 280 | + die("memory allocation failed - maybe length is too large?\n"); | |
| 281 | + /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ | |
| 282 | + memset(*src, 0, length); | |
| 283 | +} | |
| 284 | + | |
| 285 | +static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault) | |
| 286 | +{ | |
| 287 | + u64 cycle_start = 0ULL, cycle_end = 0ULL; | |
| 288 | + void *src = NULL, *dst = NULL; | |
| 289 | + memcpy_t fn = r->fn.memcpy; | |
| 290 | + int i; | |
| 291 | + | |
| 292 | + memcpy_alloc_mem(&src, &dst, len); | |
| 293 | + | |
| 294 | + if (prefault) | |
| 295 | + fn(dst, src, len); | |
| 296 | + | |
| 297 | + cycle_start = get_cycle(); | |
| 298 | + for (i = 0; i < iterations; ++i) | |
| 299 | + fn(dst, src, len); | |
| 300 | + cycle_end = get_cycle(); | |
| 301 | + | |
| 302 | + free(src); | |
| 303 | + free(dst); | |
| 304 | + return cycle_end - cycle_start; | |
| 305 | +} | |
| 306 | + | |
| 307 | +static double do_memcpy_gettimeofday(const struct routine *r, size_t len, | |
| 308 | + bool prefault) | |
| 309 | +{ | |
| 310 | + struct timeval tv_start, tv_end, tv_diff; | |
| 311 | + memcpy_t fn = r->fn.memcpy; | |
| 312 | + void *src = NULL, *dst = NULL; | |
| 313 | + int i; | |
| 314 | + | |
| 315 | + memcpy_alloc_mem(&src, &dst, len); | |
| 316 | + | |
| 317 | + if (prefault) | |
| 318 | + fn(dst, src, len); | |
| 319 | + | |
| 320 | + BUG_ON(gettimeofday(&tv_start, NULL)); | |
| 321 | + for (i = 0; i < iterations; ++i) | |
| 322 | + fn(dst, src, len); | |
| 323 | + BUG_ON(gettimeofday(&tv_end, NULL)); | |
| 324 | + | |
| 325 | + timersub(&tv_end, &tv_start, &tv_diff); | |
| 326 | + | |
| 327 | + free(src); | |
| 328 | + free(dst); | |
| 329 | + return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | |
| 330 | +} | |
| 331 | + | |
| 332 | +int bench_mem_memcpy(int argc, const char **argv, | |
| 333 | + const char *prefix __maybe_unused) | |
| 334 | +{ | |
| 335 | + struct bench_mem_info info = { | |
| 336 | + .routines = memcpy_routines, | |
| 337 | + .do_cycle = do_memcpy_cycle, | |
| 338 | + .do_gettimeofday = do_memcpy_gettimeofday, | |
| 339 | + .usage = bench_mem_memcpy_usage, | |
| 340 | + }; | |
| 341 | + | |
| 342 | + return bench_mem_common(argc, argv, prefix, &info); | |
| 343 | +} | |
| 344 | + | |
| 345 | +static void memset_alloc_mem(void **dst, size_t length) | |
| 346 | +{ | |
| 347 | + *dst = zalloc(length); | |
| 348 | + if (!*dst) | |
| 349 | + die("memory allocation failed - maybe length is too large?\n"); | |
| 350 | +} | |
| 351 | + | |
| 352 | +static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault) | |
| 353 | +{ | |
| 354 | + u64 cycle_start = 0ULL, cycle_end = 0ULL; | |
| 355 | + memset_t fn = r->fn.memset; | |
| 356 | + void *dst = NULL; | |
| 357 | + int i; | |
| 358 | + | |
| 359 | + memset_alloc_mem(&dst, len); | |
| 360 | + | |
| 361 | + if (prefault) | |
| 362 | + fn(dst, -1, len); | |
| 363 | + | |
| 364 | + cycle_start = get_cycle(); | |
| 365 | + for (i = 0; i < iterations; ++i) | |
| 366 | + fn(dst, i, len); | |
| 367 | + cycle_end = get_cycle(); | |
| 368 | + | |
| 369 | + free(dst); | |
| 370 | + return cycle_end - cycle_start; | |
| 371 | +} | |
| 372 | + | |
| 373 | +static double do_memset_gettimeofday(const struct routine *r, size_t len, | |
| 374 | + bool prefault) | |
| 375 | +{ | |
| 376 | + struct timeval tv_start, tv_end, tv_diff; | |
| 377 | + memset_t fn = r->fn.memset; | |
| 378 | + void *dst = NULL; | |
| 379 | + int i; | |
| 380 | + | |
| 381 | + memset_alloc_mem(&dst, len); | |
| 382 | + | |
| 383 | + if (prefault) | |
| 384 | + fn(dst, -1, len); | |
| 385 | + | |
| 386 | + BUG_ON(gettimeofday(&tv_start, NULL)); | |
| 387 | + for (i = 0; i < iterations; ++i) | |
| 388 | + fn(dst, i, len); | |
| 389 | + BUG_ON(gettimeofday(&tv_end, NULL)); | |
| 390 | + | |
| 391 | + timersub(&tv_end, &tv_start, &tv_diff); | |
| 392 | + | |
| 393 | + free(dst); | |
| 394 | + return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | |
| 395 | +} | |
| 396 | + | |
| 397 | +static const char * const bench_mem_memset_usage[] = { | |
| 398 | + "perf bench mem memset <options>", | |
| 399 | + NULL | |
| 400 | +}; | |
| 401 | + | |
| 402 | +static const struct routine memset_routines[] = { | |
| 403 | + { .name ="default", | |
| 404 | + .desc = "Default memset() provided by glibc", | |
| 405 | + .fn.memset = memset }, | |
| 406 | +#ifdef HAVE_ARCH_X86_64_SUPPORT | |
| 407 | + | |
| 408 | +#define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn }, | |
| 409 | +#include "mem-memset-x86-64-asm-def.h" | |
| 410 | +#undef MEMSET_FN | |
| 411 | + | |
| 412 | +#endif | |
| 413 | + | |
| 414 | + { .name = NULL, | |
| 415 | + .desc = NULL, | |
| 416 | + .fn.memset = NULL } | |
| 417 | +}; | |
| 418 | + | |
| 419 | +int bench_mem_memset(int argc, const char **argv, | |
| 420 | + const char *prefix __maybe_unused) | |
| 421 | +{ | |
| 422 | + struct bench_mem_info info = { | |
| 423 | + .routines = memset_routines, | |
| 424 | + .do_cycle = do_memset_cycle, | |
| 425 | + .do_gettimeofday = do_memset_gettimeofday, | |
| 426 | + .usage = bench_mem_memset_usage, | |
| 427 | + }; | |
| 428 | + | |
| 429 | + return bench_mem_common(argc, argv, prefix, &info); | |
| 430 | +} | |
| @@ -1,304 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * mem-memset.c | |
| 3 | − * | |
| 4 | − * memset: Simple memory set in various ways | |
| 5 | − * | |
| 6 | − * Trivial clone of mem-memcpy.c. | |
| 7 | − */ | |
| 8 | − | |
| 9 | −#include "../perf.h" | |
| 10 | −#include "../util/util.h" | |
| 11 | −#include "../util/parse-options.h" | |
| 12 | −#include "../util/header.h" | |
| 13 | −#include "../util/cloexec.h" | |
| 14 | −#include "bench.h" | |
| 15 | −#include "mem-memset-arch.h" | |
| 16 | − | |
| 17 | −#include <stdio.h> | |
| 18 | −#include <stdlib.h> | |
| 19 | −#include <string.h> | |
| 20 | −#include <sys/time.h> | |
| 21 | −#include <errno.h> | |
| 22 | − | |
| 23 | −#define K 1024 | |
| 24 | − | |
| 25 | −static const char *length_str = "1MB"; | |
| 26 | −static const char *routine = "default"; | |
| 27 | −static int iterations = 1; | |
| 28 | −static bool use_cycle; | |
| 29 | −static int cycle_fd; | |
| 30 | −static bool only_prefault; | |
| 31 | −static bool no_prefault; | |
| 32 | − | |
| 33 | −static const struct option options[] = { | |
| 34 | − OPT_STRING('l', "length", &length_str, "1MB", | |
| 35 | − "Specify length of memory to set. " | |
| 36 | − "Available units: B, KB, MB, GB and TB (upper and lower)"), | |
| 37 | − OPT_STRING('r', "routine", &routine, "default", | |
| 38 | − "Specify routine to set"), | |
| 39 | − OPT_INTEGER('i', "iterations", &iterations, | |
| 40 | − "repeat memset() invocation this number of times"), | |
| 41 | − OPT_BOOLEAN('c', "cycle", &use_cycle, | |
| 42 | − "Use cycles event instead of gettimeofday() for measuring"), | |
| 43 | − OPT_BOOLEAN('o', "only-prefault", &only_prefault, | |
| 44 | − "Show only the result with page faults before memset()"), | |
| 45 | − OPT_BOOLEAN('n', "no-prefault", &no_prefault, | |
| 46 | − "Show only the result without page faults before memset()"), | |
| 47 | − OPT_END() | |
| 48 | −}; | |
| 49 | − | |
| 50 | −typedef void *(*memset_t)(void *, int, size_t); | |
| 51 | − | |
| 52 | −struct routine { | |
| 53 | − const char *name; | |
| 54 | − const char *desc; | |
| 55 | − memset_t fn; | |
| 56 | −}; | |
| 57 | − | |
| 58 | −static const struct routine routines[] = { | |
| 59 | − { "default", | |
| 60 | − "Default memset() provided by glibc", | |
| 61 | − memset }, | |
| 62 | −#ifdef HAVE_ARCH_X86_64_SUPPORT | |
| 63 | − | |
| 64 | −#define MEMSET_FN(fn, name, desc) { name, desc, fn }, | |
| 65 | −#include "mem-memset-x86-64-asm-def.h" | |
| 66 | −#undef MEMSET_FN | |
| 67 | − | |
| 68 | −#endif | |
| 69 | − | |
| 70 | − { NULL, | |
| 71 | − NULL, | |
| 72 | − NULL } | |
| 73 | −}; | |
| 74 | − | |
| 75 | −static const char * const bench_mem_memset_usage[] = { | |
| 76 | − "perf bench mem memset <options>", | |
| 77 | − NULL | |
| 78 | −}; | |
| 79 | − | |
| 80 | −static struct perf_event_attr cycle_attr = { | |
| 81 | − .type = PERF_TYPE_HARDWARE, | |
| 82 | − .config = PERF_COUNT_HW_CPU_CYCLES | |
| 83 | −}; | |
| 84 | − | |
| 85 | −static void init_cycle(void) | |
| 86 | −{ | |
| 87 | − cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, | |
| 88 | − perf_event_open_cloexec_flag()); | |
| 89 | − | |
| 90 | − if (cycle_fd < 0 && errno == ENOSYS) | |
| 91 | − die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | |
| 92 | − else | |
| 93 | − BUG_ON(cycle_fd < 0); | |
| 94 | −} | |
| 95 | − | |
| 96 | −static u64 get_cycle(void) | |
| 97 | −{ | |
| 98 | − int ret; | |
| 99 | − u64 clk; | |
| 100 | − | |
| 101 | − ret = read(cycle_fd, &clk, sizeof(u64)); | |
| 102 | − BUG_ON(ret != sizeof(u64)); | |
| 103 | − | |
| 104 | − return clk; | |
| 105 | −} | |
| 106 | − | |
| 107 | −static double timeval2double(struct timeval *ts) | |
| 108 | −{ | |
| 109 | − return (double)ts->tv_sec + | |
| 110 | − (double)ts->tv_usec / (double)1000000; | |
| 111 | −} | |
| 112 | − | |
| 113 | −static void alloc_mem(void **dst, size_t length) | |
| 114 | −{ | |
| 115 | − *dst = zalloc(length); | |
| 116 | − if (!*dst) | |
| 117 | − die("memory allocation failed - maybe length is too large?\n"); | |
| 118 | −} | |
| 119 | − | |
| 120 | −static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault) | |
| 121 | −{ | |
| 122 | − u64 cycle_start = 0ULL, cycle_end = 0ULL; | |
| 123 | − void *dst = NULL; | |
| 124 | − int i; | |
| 125 | − | |
| 126 | − alloc_mem(&dst, len); | |
| 127 | − | |
| 128 | − if (prefault) | |
| 129 | − fn(dst, -1, len); | |
| 130 | − | |
| 131 | − cycle_start = get_cycle(); | |
| 132 | − for (i = 0; i < iterations; ++i) | |
| 133 | − fn(dst, i, len); | |
| 134 | − cycle_end = get_cycle(); | |
| 135 | − | |
| 136 | − free(dst); | |
| 137 | − return cycle_end - cycle_start; | |
| 138 | −} | |
| 139 | − | |
| 140 | −static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) | |
| 141 | −{ | |
| 142 | − struct timeval tv_start, tv_end, tv_diff; | |
| 143 | − void *dst = NULL; | |
| 144 | − int i; | |
| 145 | − | |
| 146 | − alloc_mem(&dst, len); | |
| 147 | − | |
| 148 | − if (prefault) | |
| 149 | − fn(dst, -1, len); | |
| 150 | − | |
| 151 | − BUG_ON(gettimeofday(&tv_start, NULL)); | |
| 152 | − for (i = 0; i < iterations; ++i) | |
| 153 | − fn(dst, i, len); | |
| 154 | − BUG_ON(gettimeofday(&tv_end, NULL)); | |
| 155 | − | |
| 156 | − timersub(&tv_end, &tv_start, &tv_diff); | |
| 157 | − | |
| 158 | − free(dst); | |
| 159 | − return (double)((double)len / timeval2double(&tv_diff)); | |
| 160 | −} | |
| 161 | − | |
| 162 | −#define pf (no_prefault ? 0 : 1) | |
| 163 | − | |
| 164 | −#define print_bps(x) do { \ | |
| 165 | − if (x < K) \ | |
| 166 | − printf(" %14lf B/Sec", x); \ | |
| 167 | − else if (x < K * K) \ | |
| 168 | − printf(" %14lfd KB/Sec", x / K); \ | |
| 169 | − else if (x < K * K * K) \ | |
| 170 | − printf(" %14lf MB/Sec", x / K / K); \ | |
| 171 | − else \ | |
| 172 | − printf(" %14lf GB/Sec", x / K / K / K); \ | |
| 173 | − } while (0) | |
| 174 | − | |
| 175 | −int bench_mem_memset(int argc, const char **argv, | |
| 176 | − const char *prefix __maybe_unused) | |
| 177 | −{ | |
| 178 | − int i; | |
| 179 | − size_t len; | |
| 180 | − double result_bps[2]; | |
| 181 | − u64 result_cycle[2]; | |
| 182 | − | |
| 183 | − argc = parse_options(argc, argv, options, | |
| 184 | − bench_mem_memset_usage, 0); | |
| 185 | − | |
| 186 | − if (no_prefault && only_prefault) { | |
| 187 | − fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); | |
| 188 | − return 1; | |
| 189 | − } | |
| 190 | − | |
| 191 | − if (use_cycle) | |
| 192 | − init_cycle(); | |
| 193 | − | |
| 194 | − len = (size_t)perf_atoll((char *)length_str); | |
| 195 | − | |
| 196 | − result_cycle[0] = result_cycle[1] = 0ULL; | |
| 197 | − result_bps[0] = result_bps[1] = 0.0; | |
| 198 | − | |
| 199 | − if ((s64)len <= 0) { | |
| 200 | − fprintf(stderr, "Invalid length:%s\n", length_str); | |
| 201 | − return 1; | |
| 202 | − } | |
| 203 | − | |
| 204 | − /* same to without specifying either of prefault and no-prefault */ | |
| 205 | − if (only_prefault && no_prefault) | |
| 206 | − only_prefault = no_prefault = false; | |
| 207 | − | |
| 208 | − for (i = 0; routines[i].name; i++) { | |
| 209 | − if (!strcmp(routines[i].name, routine)) | |
| 210 | − break; | |
| 211 | − } | |
| 212 | − if (!routines[i].name) { | |
| 213 | − printf("Unknown routine:%s\n", routine); | |
| 214 | − printf("Available routines...\n"); | |
| 215 | − for (i = 0; routines[i].name; i++) { | |
| 216 | − printf("\t%s ... %s\n", | |
| 217 | − routines[i].name, routines[i].desc); | |
| 218 | − } | |
| 219 | − return 1; | |
| 220 | − } | |
| 221 | − | |
| 222 | − if (bench_format == BENCH_FORMAT_DEFAULT) | |
| 223 | − printf("# Copying %s Bytes ...\n\n", length_str); | |
| 224 | − | |
| 225 | − if (!only_prefault && !no_prefault) { | |
| 226 | − /* show both of results */ | |
| 227 | − if (use_cycle) { | |
| 228 | − result_cycle[0] = | |
| 229 | − do_memset_cycle(routines[i].fn, len, false); | |
| 230 | − result_cycle[1] = | |
| 231 | − do_memset_cycle(routines[i].fn, len, true); | |
| 232 | − } else { | |
| 233 | − result_bps[0] = | |
| 234 | − do_memset_gettimeofday(routines[i].fn, | |
| 235 | − len, false); | |
| 236 | − result_bps[1] = | |
| 237 | − do_memset_gettimeofday(routines[i].fn, | |
| 238 | − len, true); | |
| 239 | − } | |
| 240 | − } else { | |
| 241 | − if (use_cycle) { | |
| 242 | − result_cycle[pf] = | |
| 243 | − do_memset_cycle(routines[i].fn, | |
| 244 | − len, only_prefault); | |
| 245 | − } else { | |
| 246 | − result_bps[pf] = | |
| 247 | − do_memset_gettimeofday(routines[i].fn, | |
| 248 | − len, only_prefault); | |
| 249 | − } | |
| 250 | − } | |
| 251 | − | |
| 252 | − switch (bench_format) { | |
| 253 | − case BENCH_FORMAT_DEFAULT: | |
| 254 | − if (!only_prefault && !no_prefault) { | |
| 255 | − if (use_cycle) { | |
| 256 | − printf(" %14lf Cycle/Byte\n", | |
| 257 | − (double)result_cycle[0] | |
| 258 | − / (double)len); | |
| 259 | − printf(" %14lf Cycle/Byte (with prefault)\n ", | |
| 260 | − (double)result_cycle[1] | |
| 261 | − / (double)len); | |
| 262 | − } else { | |
| 263 | − print_bps(result_bps[0]); | |
| 264 | − printf("\n"); | |
| 265 | − print_bps(result_bps[1]); | |
| 266 | − printf(" (with prefault)\n"); | |
| 267 | − } | |
| 268 | − } else { | |
| 269 | − if (use_cycle) { | |
| 270 | − printf(" %14lf Cycle/Byte", | |
| 271 | − (double)result_cycle[pf] | |
| 272 | − / (double)len); | |
| 273 | − } else | |
| 274 | − print_bps(result_bps[pf]); | |
| 275 | − | |
| 276 | − printf("%s\n", only_prefault ? " (with prefault)" : ""); | |
| 277 | − } | |
| 278 | − break; | |
| 279 | − case BENCH_FORMAT_SIMPLE: | |
| 280 | − if (!only_prefault && !no_prefault) { | |
| 281 | − if (use_cycle) { | |
| 282 | − printf("%lf %lf\n", | |
| 283 | − (double)result_cycle[0] / (double)len, | |
| 284 | − (double)result_cycle[1] / (double)len); | |
| 285 | − } else { | |
| 286 | − printf("%lf %lf\n", | |
| 287 | − result_bps[0], result_bps[1]); | |
| 288 | − } | |
| 289 | − } else { | |
| 290 | − if (use_cycle) { | |
| 291 | − printf("%lf\n", (double)result_cycle[pf] | |
| 292 | − / (double)len); | |
| 293 | − } else | |
| 294 | − printf("%lf\n", result_bps[pf]); | |
| 295 | − } | |
| 296 | − break; | |
| 297 | − default: | |
| 298 | − /* reaching this means there's some disaster: */ | |
| 299 | − die("unknown format: %d\n", bench_format); | |
| 300 | − break; | |
| 301 | − } | |
| 302 | − | |
| 303 | − return 0; | |
| 304 | −} | |
| @@ -285,12 +285,11 @@ int cmd_buildid_cache(int argc, const char **argv, · 284 unmodified lines | ||
| 285 | 285 | struct str_node *pos; |
| 286 | 286 | int ret = 0; |
| 287 | 287 | bool force = false; |
| 288 | − char debugdir[PATH_MAX]; | |
| 289 | 288 | char const *add_name_list_str = NULL, |
| 290 | 289 | *remove_name_list_str = NULL, |
| 291 | 290 | *missing_filename = NULL, |
| 292 | 291 | *update_name_list_str = NULL, |
| 293 | − *kcore_filename; | |
| 292 | + *kcore_filename = NULL; | |
| 294 | 293 | char sbuf[STRERR_BUFSIZE]; |
| 295 | 294 | |
| 296 | 295 | struct perf_data_file file = { |
| @@ -335,13 +334,11 @@ int cmd_buildid_cache(int argc, const char **argv, · 38 unmodified lines | ||
| 335 | 334 | |
| 336 | 335 | setup_pager(); |
| 337 | 336 | |
| 338 | − snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | |
| 339 | − | |
| 340 | 337 | if (add_name_list_str) { |
| 341 | 338 | list = strlist__new(true, add_name_list_str); |
| 342 | 339 | if (list) { |
| 343 | 340 | strlist__for_each(pos, list) |
| 344 | − if (build_id_cache__add_file(pos->s, debugdir)) { | |
| 341 | + if (build_id_cache__add_file(pos->s, buildid_dir)) { | |
| 345 | 342 | if (errno == EEXIST) { |
| 346 | 343 | pr_debug("%s already in the cache\n", |
| 347 | 344 | pos->s); |
| @@ -359,7 +356,7 @@ int cmd_buildid_cache(int argc, const char **argv, · 11 unmodified lines | ||
| 359 | 356 | list = strlist__new(true, remove_name_list_str); |
| 360 | 357 | if (list) { |
| 361 | 358 | strlist__for_each(pos, list) |
| 362 | − if (build_id_cache__remove_file(pos->s, debugdir)) { | |
| 359 | + if (build_id_cache__remove_file(pos->s, buildid_dir)) { | |
| 363 | 360 | if (errno == ENOENT) { |
| 364 | 361 | pr_debug("%s wasn't in the cache\n", |
| 365 | 362 | pos->s); |
| @@ -380,7 +377,7 @@ int cmd_buildid_cache(int argc, const char **argv, · 14 unmodified lines | ||
| 380 | 377 | list = strlist__new(true, update_name_list_str); |
| 381 | 378 | if (list) { |
| 382 | 379 | strlist__for_each(pos, list) |
| 383 | − if (build_id_cache__update_file(pos->s, debugdir)) { | |
| 380 | + if (build_id_cache__update_file(pos->s, buildid_dir)) { | |
| 384 | 381 | if (errno == ENOENT) { |
| 385 | 382 | pr_debug("%s wasn't in the cache\n", |
| 386 | 383 | pos->s); |
| @@ -395,7 +392,7 @@ int cmd_buildid_cache(int argc, const char **argv, · 8 unmodified lines | ||
| 395 | 392 | } |
| 396 | 393 | |
| 397 | 394 | if (kcore_filename && |
| 398 | − build_id_cache__add_kcore(kcore_filename, debugdir, force)) | |
| 395 | + build_id_cache__add_kcore(kcore_filename, buildid_dir, force)) | |
| 399 | 396 | pr_warning("Couldn't add %s\n", kcore_filename); |
| 400 | 397 | |
| 401 | 398 | out: |
| @@ -1293,7 +1293,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, · 1292 unmodified lines | ||
| 1293 | 1293 | OPT_UINTEGER('d', "display", &kvm->display_time, |
| 1294 | 1294 | "time in seconds between display updates"), |
| 1295 | 1295 | OPT_STRING(0, "event", &kvm->report_event, "report event", |
| 1296 | − "event for reporting: vmexit, mmio, ioport"), | |
| 1296 | + "event for reporting: " | |
| 1297 | + "vmexit, mmio (x86 only), ioport (x86 only)"), | |
| 1297 | 1298 | OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, |
| 1298 | 1299 | "vcpu id to report"), |
| 1299 | 1300 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", |
| @@ -2045,7 +2045,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv) · 2044 unmodified lines | ||
| 2045 | 2045 | unsigned long before; |
| 2046 | 2046 | const bool forks = argc > 0; |
| 2047 | 2047 | bool draining = false; |
| 2048 | − char sbuf[STRERR_BUFSIZE]; | |
| 2049 | 2048 | |
| 2050 | 2049 | trace->live = true; |
| 2051 | 2050 | |
| @@ -2106,11 +2105,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv) · 54 unmodified lines | ||
| 2106 | 2105 | goto out_error_open; |
| 2107 | 2106 | |
| 2108 | 2107 | err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); |
| 2109 | − if (err < 0) { | |
| 2110 | − fprintf(trace->output, "Couldn't mmap the events: %s\n", | |
| 2111 | − strerror_r(errno, sbuf, sizeof(sbuf))); | |
| 2112 | − goto out_delete_evlist; | |
| 2113 | − } | |
| 2108 | + if (err < 0) | |
| 2109 | + goto out_error_mmap; | |
| 2114 | 2110 | |
| 2115 | 2111 | perf_evlist__enable(evlist); |
| 2116 | 2112 | |
| @@ -2210,6 +2206,10 @@ out_error_tp: · 93 unmodified lines | ||
| 2210 | 2206 | perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); |
| 2211 | 2207 | goto out_error; |
| 2212 | 2208 | |
| 2209 | +out_error_mmap: | |
| 2210 | + perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); | |
| 2211 | + goto out_error; | |
| 2212 | + | |
| 2213 | 2213 | out_error_open: |
| 2214 | 2214 | perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); |
| 2215 | 2215 | |
| @@ -200,6 +200,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) · 199 unmodified lines | ||
| 200 | 200 | *envchanged = 1; |
| 201 | 201 | (*argv)++; |
| 202 | 202 | (*argc)--; |
| 203 | + } else if (!strcmp(cmd, "--buildid-dir")) { | |
| 204 | + if (*argc < 2) { | |
| 205 | + fprintf(stderr, "No directory given for --buildid-dir.\n"); | |
| 206 | + usage(perf_usage_string); | |
| 207 | + } | |
| 208 | + set_buildid_dir((*argv)[1]); | |
| 209 | + if (envchanged) | |
| 210 | + *envchanged = 1; | |
| 211 | + (*argv)++; | |
| 212 | + (*argc)--; | |
| 203 | 213 | } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { |
| 204 | 214 | perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); |
| 205 | 215 | fprintf(stderr, "dir: %s\n", debugfs_mountpoint); |
| @@ -499,7 +509,7 @@ int main(int argc, const char **argv) · 293 unmodified lines | ||
| 499 | 509 | } |
| 500 | 510 | if (!prefixcmp(cmd, "trace")) { |
| 501 | 511 | #ifdef HAVE_LIBAUDIT_SUPPORT |
| 502 | − set_buildid_dir(); | |
| 512 | + set_buildid_dir(NULL); | |
| 503 | 513 | setup_path(); |
| 504 | 514 | argv[0] = "trace"; |
| 505 | 515 | return cmd_trace(argc, argv, NULL); |
| @@ -514,7 +524,7 @@ int main(int argc, const char **argv) · 8 unmodified lines | ||
| 514 | 524 | argc--; |
| 515 | 525 | handle_options(&argv, &argc, NULL); |
| 516 | 526 | commit_pager_choice(); |
| 517 | − set_buildid_dir(); | |
| 527 | + set_buildid_dir(NULL); | |
| 518 | 528 | |
| 519 | 529 | if (argc > 0) { |
| 520 | 530 | if (!prefixcmp(argv[0], "--")) |
| @@ -5,7 +5,7 @@ group_fd=-1 · 4 unmodified lines | ||
| 5 | 5 | flags=0|8 |
| 6 | 6 | cpu=* |
| 7 | 7 | type=0|1 |
| 8 | −size=96 | |
| 8 | +size=104 | |
| 9 | 9 | config=0 |
| 10 | 10 | sample_period=4000 |
| 11 | 11 | sample_type=263 |
| @@ -5,7 +5,7 @@ group_fd=-1 · 4 unmodified lines | ||
| 5 | 5 | flags=0|8 |
| 6 | 6 | cpu=* |
| 7 | 7 | type=0 |
| 8 | −size=96 | |
| 8 | +size=104 | |
| 9 | 9 | config=0 |
| 10 | 10 | sample_period=0 |
| 11 | 11 | sample_type=0 |
| @@ -1252,7 +1252,7 @@ static int hists__browser_title(struct hists *hists, · 1251 unmodified lines | ||
| 1252 | 1252 | |
| 1253 | 1253 | nr_samples = convert_unit(nr_samples, &unit); |
| 1254 | 1254 | printed = scnprintf(bf, size, |
| 1255 | − "Samples: %lu%c of event '%s', Event count (approx.): %lu", | |
| 1255 | + "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64, | |
| 1256 | 1256 | nr_samples, unit, ev_name, nr_events); |
| 1257 | 1257 | |
| 1258 | 1258 | |
| @@ -162,8 +162,8 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, · 161 unmodified lines | ||
| 162 | 162 | return ret; |
| 163 | 163 | |
| 164 | 164 | nr_members = evsel->nr_members; |
| 165 | − fields_a = calloc(sizeof(*fields_a), nr_members); | |
| 166 | − fields_b = calloc(sizeof(*fields_b), nr_members); | |
| 165 | + fields_a = calloc(nr_members, sizeof(*fields_a)); | |
| 166 | + fields_b = calloc(nr_members, sizeof(*fields_b)); | |
| 167 | 167 | |
| 168 | 168 | if (!fields_a || !fields_b) |
| 169 | 169 | goto out; |
| @@ -410,21 +410,18 @@ int perf_session__cache_build_ids(struct perf_session *session) · 409 unmodified lines | ||
| 410 | 410 | { |
| 411 | 411 | struct rb_node *nd; |
| 412 | 412 | int ret; |
| 413 | − char debugdir[PATH_MAX]; | |
| 414 | 413 | |
| 415 | 414 | if (no_buildid_cache) |
| 416 | 415 | return 0; |
| 417 | 416 | |
| 418 | − snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); | |
| 419 | − | |
| 420 | − if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | |
| 417 | + if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) | |
| 421 | 418 | return -1; |
| 422 | 419 | |
| 423 | − ret = machine__cache_build_ids(&session->machines.host, debugdir); | |
| 420 | + ret = machine__cache_build_ids(&session->machines.host, buildid_dir); | |
| 424 | 421 | |
| 425 | 422 | for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { |
| 426 | 423 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
| 427 | − ret |= machine__cache_build_ids(pos, debugdir); | |
| 424 | + ret |= machine__cache_build_ids(pos, buildid_dir); | |
| 428 | 425 | } |
| 429 | 426 | return ret ? -1 : 0; |
| 430 | 427 | } |
| @@ -77,7 +77,7 @@ int parse_callchain_record_opt(const char *arg) · 76 unmodified lines | ||
| 77 | 77 | ret = 0; |
| 78 | 78 | } else |
| 79 | 79 | pr_err("callchain: No more arguments " |
| 80 | − "needed for -g fp\n"); | |
| 80 | + "needed for --call-graph fp\n"); | |
| 81 | 81 | break; |
| 82 | 82 | |
| 83 | 83 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
| @@ -522,7 +522,7 @@ static int buildid_dir_command_config(const char *var, const char *value, · 521 unmodified lines | ||
| 522 | 522 | const char *v; |
| 523 | 523 | |
| 524 | 524 | /* same dir for all commands */ |
| 525 | − if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) { | |
| 525 | + if (!strcmp(var, "buildid.dir")) { | |
| 526 | 526 | v = perf_config_dirname(var, value); |
| 527 | 527 | if (!v) |
| 528 | 528 | return -1; |
| @@ -539,12 +539,14 @@ static void check_buildid_dir_config(void) · 10 unmodified lines | ||
| 539 | 539 | perf_config(buildid_dir_command_config, &c); |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | −void set_buildid_dir(void) | |
| 542 | +void set_buildid_dir(const char *dir) | |
| 543 | 543 | { |
| 544 | − buildid_dir[0] = '\0'; | |
| 544 | + if (dir) | |
| 545 | + scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); | |
| 545 | 546 | |
| 546 | 547 | /* try config file */ |
| 547 | − check_buildid_dir_config(); | |
| 548 | + if (buildid_dir[0] == '\0') | |
| 549 | + check_buildid_dir_config(); | |
| 548 | 550 | |
| 549 | 551 | /* default to $HOME/.debug */ |
| 550 | 552 | if (buildid_dir[0] == '\0') { |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | */ |
| 9 | 9 | #include "util.h" |
| 10 | 10 | #include <api/fs/debugfs.h> |
| 11 | +#include <api/fs/fs.h> | |
| 11 | 12 | #include <poll.h> |
| 12 | 13 | #include "cpumap.h" |
| 13 | 14 | #include "thread_map.h" |
| @@ -1483,6 +1484,28 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, · 1469 unmodified lines | ||
| 1483 | 1484 | return 0; |
| 1484 | 1485 | } |
| 1485 | 1486 | |
| 1487 | +int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) | |
| 1488 | +{ | |
| 1489 | + char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | |
| 1490 | + int value; | |
| 1491 | + | |
| 1492 | + switch (err) { | |
| 1493 | + case EPERM: | |
| 1494 | + sysctl__read_int("kernel/perf_event_mlock_kb", &value); | |
| 1495 | + scnprintf(buf, size, "Error:\t%s.\n" | |
| 1496 | + "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n" | |
| 1497 | + "Hint:\tTried using %zd kB.\n" | |
| 1498 | + "Hint:\tTry using a bigger -m/--mmap-pages value.", | |
| 1499 | + emsg, value, evlist->mmap_len / 1024); | |
| 1500 | + break; | |
| 1501 | + default: | |
| 1502 | + scnprintf(buf, size, "%s", emsg); | |
| 1503 | + break; | |
| 1504 | + } | |
| 1505 | + | |
| 1506 | + return 0; | |
| 1507 | +} | |
| 1508 | + | |
| 1486 | 1509 | void perf_evlist__to_front(struct perf_evlist *evlist, |
| 1487 | 1510 | struct perf_evsel *move_evsel) |
| 1488 | 1511 | { |
| @@ -185,6 +185,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); · 184 unmodified lines | ||
| 185 | 185 | |
| 186 | 186 | int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); |
| 187 | 187 | int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); |
| 188 | +int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); | |
| 188 | 189 | |
| 189 | 190 | static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) |
| 190 | 191 | { |
| @@ -1385,19 +1385,46 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, · 1384 unmodified lines | ||
| 1385 | 1385 | static int add_callchain_ip(struct thread *thread, |
| 1386 | 1386 | struct symbol **parent, |
| 1387 | 1387 | struct addr_location *root_al, |
| 1388 | − int cpumode, | |
| 1388 | + bool branch_history, | |
| 1389 | 1389 | u64 ip) |
| 1390 | 1390 | { |
| 1391 | 1391 | struct addr_location al; |
| 1392 | 1392 | |
| 1393 | 1393 | al.filtered = 0; |
| 1394 | 1394 | al.sym = NULL; |
| 1395 | − if (cpumode == -1) | |
| 1395 | + if (branch_history) | |
| 1396 | 1396 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, |
| 1397 | 1397 | ip, &al); |
| 1398 | − else | |
| 1398 | + else { | |
| 1399 | + u8 cpumode = PERF_RECORD_MISC_USER; | |
| 1400 | + | |
| 1401 | + if (ip >= PERF_CONTEXT_MAX) { | |
| 1402 | + switch (ip) { | |
| 1403 | + case PERF_CONTEXT_HV: | |
| 1404 | + cpumode = PERF_RECORD_MISC_HYPERVISOR; | |
| 1405 | + break; | |
| 1406 | + case PERF_CONTEXT_KERNEL: | |
| 1407 | + cpumode = PERF_RECORD_MISC_KERNEL; | |
| 1408 | + break; | |
| 1409 | + case PERF_CONTEXT_USER: | |
| 1410 | + cpumode = PERF_RECORD_MISC_USER; | |
| 1411 | + break; | |
| 1412 | + default: | |
| 1413 | + pr_debug("invalid callchain context: " | |
| 1414 | + "%"PRId64"\n", (s64) ip); | |
| 1415 | + /* | |
| 1416 | + * It seems the callchain is corrupted. | |
| 1417 | + * Discard all. | |
| 1418 | + */ | |
| 1419 | + callchain_cursor_reset(&callchain_cursor); | |
| 1420 | + return 1; | |
| 1421 | + } | |
| 1422 | + return 0; | |
| 1423 | + } | |
| 1399 | 1424 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, |
| 1400 | 1425 | ip, &al); |
| 1426 | + } | |
| 1427 | + | |
| 1401 | 1428 | if (al.sym != NULL) { |
| 1402 | 1429 | if (sort__has_parent && !*parent && |
| 1403 | 1430 | symbol__match_regex(al.sym, &parent_regex)) |
| @@ -1480,11 +1507,8 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 76 unmodified lines | ||
| 1480 | 1507 | struct addr_location *root_al, |
| 1481 | 1508 | int max_stack) |
| 1482 | 1509 | { |
| 1483 | − u8 cpumode = PERF_RECORD_MISC_USER; | |
| 1484 | 1510 | int chain_nr = min(max_stack, (int)chain->nr); |
| 1485 | − int i; | |
| 1486 | − int j; | |
| 1487 | − int err; | |
| 1511 | + int i, j, err; | |
| 1488 | 1512 | int skip_idx = -1; |
| 1489 | 1513 | int first_call = 0; |
| 1490 | 1514 | |
| @@ -1542,10 +1566,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 51 unmodified lines | ||
| 1542 | 1566 | |
| 1543 | 1567 | for (i = 0; i < nr; i++) { |
| 1544 | 1568 | err = add_callchain_ip(thread, parent, root_al, |
| 1545 | − -1, be[i].to); | |
| 1569 | + true, be[i].to); | |
| 1546 | 1570 | if (!err) |
| 1547 | 1571 | err = add_callchain_ip(thread, parent, root_al, |
| 1548 | − -1, be[i].from); | |
| 1572 | + true, be[i].from); | |
| 1549 | 1573 | if (err == -EINVAL) |
| 1550 | 1574 | break; |
| 1551 | 1575 | if (err) |
| @@ -1574,36 +1598,10 @@ check_calls: · 22 unmodified lines | ||
| 1574 | 1598 | #endif |
| 1575 | 1599 | ip = chain->ips[j]; |
| 1576 | 1600 | |
| 1577 | − if (ip >= PERF_CONTEXT_MAX) { | |
| 1578 | − switch (ip) { | |
| 1579 | − case PERF_CONTEXT_HV: | |
| 1580 | − cpumode = PERF_RECORD_MISC_HYPERVISOR; | |
| 1581 | − break; | |
| 1582 | − case PERF_CONTEXT_KERNEL: | |
| 1583 | − cpumode = PERF_RECORD_MISC_KERNEL; | |
| 1584 | − break; | |
| 1585 | − case PERF_CONTEXT_USER: | |
| 1586 | − cpumode = PERF_RECORD_MISC_USER; | |
| 1587 | − break; | |
| 1588 | − default: | |
| 1589 | − pr_debug("invalid callchain context: " | |
| 1590 | − "%"PRId64"\n", (s64) ip); | |
| 1591 | − /* | |
| 1592 | − * It seems the callchain is corrupted. | |
| 1593 | − * Discard all. | |
| 1594 | − */ | |
| 1595 | − callchain_cursor_reset(&callchain_cursor); | |
| 1596 | − return 0; | |
| 1597 | − } | |
| 1598 | − continue; | |
| 1599 | − } | |
| 1601 | + err = add_callchain_ip(thread, parent, root_al, false, ip); | |
| 1600 | 1602 | |
| 1601 | − err = add_callchain_ip(thread, parent, root_al, | |
| 1602 | − cpumode, ip); | |
| 1603 | − if (err == -EINVAL) | |
| 1604 | − break; | |
| 1605 | 1603 | if (err) |
| 1606 | − return err; | |
| 1604 | + return (err < 0) ? err : 0; | |
| 1607 | 1605 | } |
| 1608 | 1606 | |
| 1609 | 1607 | return 0; |
| @@ -137,16 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) · 136 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | static int get_max_rate(unsigned int *rate) |
| 139 | 139 | { |
| 140 | − char path[PATH_MAX]; | |
| 141 | − const char *procfs = procfs__mountpoint(); | |
| 142 | − | |
| 143 | − if (!procfs) | |
| 144 | − return -1; | |
| 145 | − | |
| 146 | − snprintf(path, PATH_MAX, | |
| 147 | − "%s/sys/kernel/perf_event_max_sample_rate", procfs); | |
| 148 | − | |
| 149 | − return filename__read_int(path, (int *) rate); | |
| 140 | + return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate); | |
| 150 | 141 | } |
| 151 | 142 | |
| 152 | 143 | static int record_opts__config_freq(struct record_opts *opts) |
| @@ -442,23 +442,6 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags) · 441 unmodified lines | ||
| 442 | 442 | return (unsigned long) -1; |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | −int filename__read_int(const char *filename, int *value) | |
| 446 | −{ | |
| 447 | − char line[64]; | |
| 448 | − int fd = open(filename, O_RDONLY), err = -1; | |
| 449 | − | |
| 450 | − if (fd < 0) | |
| 451 | − return -1; | |
| 452 | − | |
| 453 | − if (read(fd, line, sizeof(line)) > 0) { | |
| 454 | − *value = atoi(line); | |
| 455 | − err = 0; | |
| 456 | − } | |
| 457 | − | |
| 458 | − close(fd); | |
| 459 | − return err; | |
| 460 | −} | |
| 461 | − | |
| 462 | 445 | int filename__read_str(const char *filename, char **buf, size_t *sizep) |
| 463 | 446 | { |
| 464 | 447 | size_t size = 0, alloc_size = 0; |
| @@ -523,16 +506,9 @@ const char *get_filename_for_perf_kvm(void) · 58 unmodified lines | ||
| 523 | 506 | |
| 524 | 507 | int perf_event_paranoid(void) |
| 525 | 508 | { |
| 526 | − char path[PATH_MAX]; | |
| 527 | − const char *procfs = procfs__mountpoint(); | |
| 528 | 509 | int value; |
| 529 | 510 | |
| 530 | − if (!procfs) | |
| 531 | − return INT_MAX; | |
| 532 | − | |
| 533 | − scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); | |
| 534 | − | |
| 535 | − if (filename__read_int(path, &value)) | |
| 511 | + if (sysctl__read_int("kernel/perf_event_paranoid", &value)) | |
| 536 | 512 | return INT_MAX; |
| 537 | 513 | |
| 538 | 514 | return value; |
| @@ -153,7 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) · 152 unmodified lines | ||
| 153 | 153 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); |
| 154 | 154 | |
| 155 | 155 | extern int prefixcmp(const char *str, const char *prefix); |
| 156 | −extern void set_buildid_dir(void); | |
| 156 | +extern void set_buildid_dir(const char *dir); | |
| 157 | 157 | |
| 158 | 158 | static inline const char *skip_prefix(const char *str, const char *prefix) |
| 159 | 159 | { |
| @@ -343,7 +343,6 @@ char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym, · 183 unmodified lines | ||
| 343 | 343 | bool show_sym); |
| 344 | 344 | void free_srcline(char *srcline); |
| 345 | 345 | |
| 346 | −int filename__read_int(const char *filename, int *value); | |
| 347 | 346 | int filename__read_str(const char *filename, char **buf, size_t *sizep); |
| 348 | 347 | int perf_event_paranoid(void); |
| 349 | 348 | |
| @@ -446,7 +446,7 @@ int probe_thermal_sysfs(void) · 445 unmodified lines | ||
| 446 | 446 | return -1; |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | − ptdata.tzi = calloc(sizeof(struct tz_info), ptdata.max_tz_instance+1); | |
| 449 | + ptdata.tzi = calloc(ptdata.max_tz_instance+1, sizeof(struct tz_info)); | |
| 450 | 450 | if (!ptdata.tzi) { |
| 451 | 451 | fprintf(stderr, "Err: allocate tz_info\n"); |
| 452 | 452 | return -1; |
| @@ -454,8 +454,8 @@ int probe_thermal_sysfs(void) · 1 unmodified line | ||
| 454 | 454 | |
| 455 | 455 | /* we still show thermal zone information if there is no cdev */ |
| 456 | 456 | if (ptdata.nr_cooling_dev) { |
| 457 | − ptdata.cdi = calloc(sizeof(struct cdev_info), | |
| 458 | − ptdata.max_cdev_instance + 1); | |
| 457 | + ptdata.cdi = calloc(ptdata.max_cdev_instance + 1, | |
| 458 | + sizeof(struct cdev_info)); | |
| 459 | 459 | if (!ptdata.cdi) { |
| 460 | 460 | free(ptdata.tzi); |
| 461 | 461 | fprintf(stderr, "Err: allocate cdev_info\n"); |