Commit 40d4f23f authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes:

User visible changes:

  - 'perf bench mem' now prefaults unconditionally, no sense in
    providing modes where page faults are measured. (Ingo Molnar)

  - Harmonize -l/--nr_loops accross 'perf bench'. (Ingo Molnar)

  - Various 'perf bench' consistency improvements. (Ingo Molnar)

  - Suppress libtraceevent warnings in non-verbose 'perf test' mode.
    (Namhyung Kim)

  - Move some tracepoint event test error messages to the verbose mode
    of 'perf test'. (Namhyung Kim)

  - Make 'perf help' usage message consistent with other tools. (Yunlong Song)

Build fixes:

  - Fix 'perf bench' build with gcc 4.4.7. (Arnaldo Carvalho de Melo)

Infrastructure changes:

  - 'perf stat' prep work for the 'perf stat scripting' patchkit. (Jiri Olsa)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents e9363dee a4c6a3e8
...@@ -82,7 +82,7 @@ Be multi thread instead of multi process ...@@ -82,7 +82,7 @@ Be multi thread instead of multi process
Specify number of groups Specify number of groups
-l:: -l::
--loop=:: --nr_loops=::
Specify number of loops Specify number of loops
Example of *messaging* Example of *messaging*
...@@ -139,64 +139,48 @@ Suite for evaluating performance of simple memory copy in various ways. ...@@ -139,64 +139,48 @@ Suite for evaluating performance of simple memory copy in various ways.
Options of *memcpy* Options of *memcpy*
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
-l:: -l::
--length:: --size::
Specify length of memory to copy (default: 1MB). Specify size of memory to copy (default: 1MB).
Available units are B, KB, MB, GB and TB (case insensitive). Available units are B, KB, MB, GB and TB (case insensitive).
-r:: -f::
--routine:: --function::
Specify routine to copy (default: default). Specify function to copy (default: default).
Available routines are depend on the architecture. Available functions are depend on the architecture.
On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
-i:: -l::
--iterations:: --nr_loops::
Repeat memcpy invocation this number of times. Repeat memcpy invocation this number of times.
-c:: -c::
--cycle:: --cycles::
Use perf's cpu-cycles event instead of gettimeofday syscall. Use perf's cpu-cycles event instead of gettimeofday syscall.
-o::
--only-prefault::
Show only the result with page faults before memcpy.
-n::
--no-prefault::
Show only the result without page faults before memcpy.
*memset*:: *memset*::
Suite for evaluating performance of simple memory set in various ways. Suite for evaluating performance of simple memory set in various ways.
Options of *memset* Options of *memset*
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
-l:: -l::
--length:: --size::
Specify length of memory to set (default: 1MB). Specify size of memory to set (default: 1MB).
Available units are B, KB, MB, GB and TB (case insensitive). Available units are B, KB, MB, GB and TB (case insensitive).
-r:: -f::
--routine:: --function::
Specify routine to set (default: default). Specify function to set (default: default).
Available routines are depend on the architecture. Available functions are depend on the architecture.
On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
-i:: -l::
--iterations:: --nr_loops::
Repeat memset invocation this number of times. Repeat memset invocation this number of times.
-c:: -c::
--cycle:: --cycles::
Use perf's cpu-cycles event instead of gettimeofday syscall. Use perf's cpu-cycles event instead of gettimeofday syscall.
-o::
--only-prefault::
Show only the result with page faults before memset.
-n::
--no-prefault::
Show only the result without page faults before memset.
SUITES FOR 'numa' SUITES FOR 'numa'
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
*mem*:: *mem*::
......
perf-y += sched-messaging.o perf-y += sched-messaging.o
perf-y += sched-pipe.o perf-y += sched-pipe.o
perf-y += mem-memcpy.o perf-y += mem-functions.o
perf-y += futex-hash.o perf-y += futex-hash.o
perf-y += futex-wake.o perf-y += futex-wake.o
perf-y += futex-wake-parallel.o perf-y += futex-wake-parallel.o
......
/*
* mem-memcpy.c
*
* Simple memcpy() and memset() benchmarks
*
* Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
*/
#include "../perf.h"
#include "../util/util.h"
#include "../util/parse-options.h"
#include "../util/header.h"
#include "../util/cloexec.h"
#include "bench.h"
#include "mem-memcpy-arch.h"
#include "mem-memset-arch.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#define K 1024
static const char *size_str = "1MB";
static const char *function_str = "all";
static int nr_loops = 1;
static bool use_cycles;
static int cycles_fd;
static const struct option options[] = {
OPT_STRING('s', "size", &size_str, "1MB",
"Specify the size of the memory buffers. "
"Available units: B, KB, MB, GB and TB (case insensitive)"),
OPT_STRING('f', "function", &function_str, "all",
"Specify the function to run, \"all\" runs all available functions, \"help\" lists them"),
OPT_INTEGER('l', "nr_loops", &nr_loops,
"Specify the number of loops to run. (default: 1)"),
OPT_BOOLEAN('c', "cycles", &use_cycles,
"Use a cycles event instead of gettimeofday() to measure performance"),
OPT_END()
};
typedef void *(*memcpy_t)(void *, const void *, size_t);
typedef void *(*memset_t)(void *, int, size_t);
struct function {
const char *name;
const char *desc;
union {
memcpy_t memcpy;
memset_t memset;
} fn;
};
static struct perf_event_attr cycle_attr = {
.type = PERF_TYPE_HARDWARE,
.config = PERF_COUNT_HW_CPU_CYCLES
};
static void init_cycles(void)
{
cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());
if (cycles_fd < 0 && errno == ENOSYS)
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
else
BUG_ON(cycles_fd < 0);
}
static u64 get_cycles(void)
{
int ret;
u64 clk;
ret = read(cycles_fd, &clk, sizeof(u64));
BUG_ON(ret != sizeof(u64));
return clk;
}
static double timeval2double(struct timeval *ts)
{
return (double)ts->tv_sec + (double)ts->tv_usec / (double)1000000;
}
#define print_bps(x) do { \
if (x < K) \
printf(" %14lf bytes/sec\n", x); \
else if (x < K * K) \
printf(" %14lfd KB/sec\n", x / K); \
else if (x < K * K * K) \
printf(" %14lf MB/sec\n", x / K / K); \
else \
printf(" %14lf GB/sec\n", x / K / K / K); \
} while (0)
struct bench_mem_info {
const struct function *functions;
u64 (*do_cycles)(const struct function *r, size_t size);
double (*do_gettimeofday)(const struct function *r, size_t size);
const char *const *usage;
};
static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total)
{
const struct function *r = &info->functions[r_idx];
double result_bps = 0.0;
u64 result_cycles = 0;
printf("# function '%s' (%s)\n", r->name, r->desc);
if (bench_format == BENCH_FORMAT_DEFAULT)
printf("# Copying %s bytes ...\n\n", size_str);
if (use_cycles) {
result_cycles = info->do_cycles(r, size);
} else {
result_bps = info->do_gettimeofday(r, size);
}
switch (bench_format) {
case BENCH_FORMAT_DEFAULT:
if (use_cycles) {
printf(" %14lf cycles/byte\n", (double)result_cycles/size_total);
} else {
print_bps(result_bps);
}
break;
case BENCH_FORMAT_SIMPLE:
if (use_cycles) {
printf("%lf\n", (double)result_cycles/size_total);
} else {
printf("%lf\n", result_bps);
}
break;
default:
BUG_ON(1);
break;
}
}
static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info)
{
int i;
size_t size;
double size_total;
argc = parse_options(argc, argv, options, info->usage, 0);
if (use_cycles)
init_cycles();
size = (size_t)perf_atoll((char *)size_str);
size_total = (double)size * nr_loops;
if ((s64)size <= 0) {
fprintf(stderr, "Invalid size:%s\n", size_str);
return 1;
}
if (!strncmp(function_str, "all", 3)) {
for (i = 0; info->functions[i].name; i++)
__bench_mem_function(info, i, size, size_total);
return 0;
}
for (i = 0; info->functions[i].name; i++) {
if (!strcmp(info->functions[i].name, function_str))
break;
}
if (!info->functions[i].name) {
if (strcmp(function_str, "help") && strcmp(function_str, "h"))
printf("Unknown function: %s\n", function_str);
printf("Available functions:\n");
for (i = 0; info->functions[i].name; i++) {
printf("\t%s ... %s\n",
info->functions[i].name, info->functions[i].desc);
}
return 1;
}
__bench_mem_function(info, i, size, size_total);
return 0;
}
static void memcpy_alloc_mem(void **dst, void **src, size_t size)
{
*dst = zalloc(size);
if (!*dst)
die("memory allocation failed - maybe size is too large?\n");
*src = zalloc(size);
if (!*src)
die("memory allocation failed - maybe size is too large?\n");
/* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
memset(*src, 0, size);
}
static u64 do_memcpy_cycles(const struct function *r, size_t size)
{
u64 cycle_start = 0ULL, cycle_end = 0ULL;
void *src = NULL, *dst = NULL;
memcpy_t fn = r->fn.memcpy;
int i;
memcpy_alloc_mem(&dst, &src, size);
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
*/
fn(dst, src, size);
cycle_start = get_cycles();
for (i = 0; i < nr_loops; ++i)
fn(dst, src, size);
cycle_end = get_cycles();
free(src);
free(dst);
return cycle_end - cycle_start;
}
static double do_memcpy_gettimeofday(const struct function *r, size_t size)
{
struct timeval tv_start, tv_end, tv_diff;
memcpy_t fn = r->fn.memcpy;
void *src = NULL, *dst = NULL;
int i;
memcpy_alloc_mem(&dst, &src, size);
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
*/
fn(dst, src, size);
BUG_ON(gettimeofday(&tv_start, NULL));
for (i = 0; i < nr_loops; ++i)
fn(dst, src, size);
BUG_ON(gettimeofday(&tv_end, NULL));
timersub(&tv_end, &tv_start, &tv_diff);
free(src);
free(dst);
return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
}
struct function memcpy_functions[] = {
{ .name = "default",
.desc = "Default memcpy() provided by glibc",
.fn.memcpy = memcpy },
#ifdef HAVE_ARCH_X86_64_SUPPORT
# define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
# include "mem-memcpy-x86-64-asm-def.h"
# undef MEMCPY_FN
#endif
{ .name = NULL, }
};
static const char * const bench_mem_memcpy_usage[] = {
"perf bench mem memcpy <options>",
NULL
};
int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct bench_mem_info info = {
.functions = memcpy_functions,
.do_cycles = do_memcpy_cycles,
.do_gettimeofday = do_memcpy_gettimeofday,
.usage = bench_mem_memcpy_usage,
};
return bench_mem_common(argc, argv, &info);
}
static void memset_alloc_mem(void **dst, size_t size)
{
*dst = zalloc(size);
if (!*dst)
die("memory allocation failed - maybe size is too large?\n");
}
static u64 do_memset_cycles(const struct function *r, size_t size)
{
u64 cycle_start = 0ULL, cycle_end = 0ULL;
memset_t fn = r->fn.memset;
void *dst = NULL;
int i;
memset_alloc_mem(&dst, size);
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
*/
fn(dst, -1, size);
cycle_start = get_cycles();
for (i = 0; i < nr_loops; ++i)
fn(dst, i, size);
cycle_end = get_cycles();
free(dst);
return cycle_end - cycle_start;
}
static double do_memset_gettimeofday(const struct function *r, size_t size)
{
struct timeval tv_start, tv_end, tv_diff;
memset_t fn = r->fn.memset;
void *dst = NULL;
int i;
memset_alloc_mem(&dst, size);
/*
* We prefault the freshly allocated memory range here,
* to not measure page fault overhead:
*/
fn(dst, -1, size);
BUG_ON(gettimeofday(&tv_start, NULL));
for (i = 0; i < nr_loops; ++i)
fn(dst, i, size);
BUG_ON(gettimeofday(&tv_end, NULL));
timersub(&tv_end, &tv_start, &tv_diff);
free(dst);
return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
}
static const char * const bench_mem_memset_usage[] = {
"perf bench mem memset <options>",
NULL
};
static const struct function memset_functions[] = {
{ .name = "default",
.desc = "Default memset() provided by glibc",
.fn.memset = memset },
#ifdef HAVE_ARCH_X86_64_SUPPORT
# define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn },
# include "mem-memset-x86-64-asm-def.h"
# undef MEMSET_FN
#endif
{ .name = NULL, }
};
int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct bench_mem_info info = {
.functions = memset_functions,
.do_cycles = do_memset_cycles,
.do_gettimeofday = do_memset_gettimeofday,
.usage = bench_mem_memset_usage,
};
return bench_mem_common(argc, argv, &info);
}
This diff is collapsed.
...@@ -164,8 +164,8 @@ static const struct option options[] = { ...@@ -164,8 +164,8 @@ static const struct option options[] = {
OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"), OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"),
OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"), OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"),
OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run"), OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run (default: unlimited)"),
OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run"), OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"),
OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"),
OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"),
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#define DATASIZE 100 #define DATASIZE 100
static bool use_pipes = false; static bool use_pipes = false;
static unsigned int loops = 100; static unsigned int nr_loops = 100;
static bool thread_mode = false; static bool thread_mode = false;
static unsigned int num_groups = 10; static unsigned int num_groups = 10;
...@@ -79,7 +79,7 @@ static void ready(int ready_out, int wakefd) ...@@ -79,7 +79,7 @@ static void ready(int ready_out, int wakefd)
err(EXIT_FAILURE, "poll"); err(EXIT_FAILURE, "poll");
} }
/* Sender sprays loops messages down each file descriptor */ /* Sender sprays nr_loops messages down each file descriptor */
static void *sender(struct sender_context *ctx) static void *sender(struct sender_context *ctx)
{ {
char data[DATASIZE]; char data[DATASIZE];
...@@ -88,7 +88,7 @@ static void *sender(struct sender_context *ctx) ...@@ -88,7 +88,7 @@ static void *sender(struct sender_context *ctx)
ready(ctx->ready_out, ctx->wakefd); ready(ctx->ready_out, ctx->wakefd);
/* Now pump to every receiver. */ /* Now pump to every receiver. */
for (i = 0; i < loops; i++) { for (i = 0; i < nr_loops; i++) {
for (j = 0; j < ctx->num_fds; j++) { for (j = 0; j < ctx->num_fds; j++) {
int ret, done = 0; int ret, done = 0;
...@@ -213,7 +213,7 @@ static unsigned int group(pthread_t *pth, ...@@ -213,7 +213,7 @@ static unsigned int group(pthread_t *pth,
/* Create the pipe between client and server */ /* Create the pipe between client and server */
fdpair(fds); fdpair(fds);
ctx->num_packets = num_fds * loops; ctx->num_packets = num_fds * nr_loops;
ctx->in_fds[0] = fds[0]; ctx->in_fds[0] = fds[0];
ctx->in_fds[1] = fds[1]; ctx->in_fds[1] = fds[1];
ctx->ready_out = ready_out; ctx->ready_out = ready_out;
...@@ -250,7 +250,7 @@ static const struct option options[] = { ...@@ -250,7 +250,7 @@ static const struct option options[] = {
OPT_BOOLEAN('t', "thread", &thread_mode, OPT_BOOLEAN('t', "thread", &thread_mode,
"Be multi thread instead of multi process"), "Be multi thread instead of multi process"),
OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"),
OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"), OPT_UINTEGER('l', "nr_loops", &nr_loops, "Specify the number of loops to run (default: 100)"),
OPT_END() OPT_END()
}; };
......
...@@ -36,7 +36,7 @@ struct bench { ...@@ -36,7 +36,7 @@ struct bench {
#ifdef HAVE_LIBNUMA_SUPPORT #ifdef HAVE_LIBNUMA_SUPPORT
static struct bench numa_benchmarks[] = { static struct bench numa_benchmarks[] = {
{ "mem", "Benchmark for NUMA workloads", bench_numa }, { "mem", "Benchmark for NUMA workloads", bench_numa },
{ "all", "Test all NUMA benchmarks", NULL }, { "all", "Run all NUMA benchmarks", NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
#endif #endif
...@@ -44,14 +44,14 @@ static struct bench numa_benchmarks[] = { ...@@ -44,14 +44,14 @@ static struct bench numa_benchmarks[] = {
static struct bench sched_benchmarks[] = { static struct bench sched_benchmarks[] = {
{ "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
{ "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
{ "all", "Test all scheduler benchmarks", NULL }, { "all", "Run all scheduler benchmarks", NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
static struct bench mem_benchmarks[] = { static struct bench mem_benchmarks[] = {
{ "memcpy", "Benchmark for memcpy()", bench_mem_memcpy }, { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy },
{ "memset", "Benchmark for memset() tests", bench_mem_memset }, { "memset", "Benchmark for memset() functions", bench_mem_memset },
{ "all", "Test all memory benchmarks", NULL }, { "all", "Run all memory access benchmarks", NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
...@@ -62,7 +62,7 @@ static struct bench futex_benchmarks[] = { ...@@ -62,7 +62,7 @@ static struct bench futex_benchmarks[] = {
{ "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue },
/* pi-futexes */ /* pi-futexes */
{ "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi },
{ "all", "Test all futex benchmarks", NULL }, { "all", "Run all futex benchmarks", NULL },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
...@@ -110,7 +110,7 @@ int bench_format = BENCH_FORMAT_DEFAULT; ...@@ -110,7 +110,7 @@ int bench_format = BENCH_FORMAT_DEFAULT;
unsigned int bench_repeat = 10; /* default number of times to repeat the run */ unsigned int bench_repeat = 10; /* default number of times to repeat the run */
static const struct option bench_options[] = { static const struct option bench_options[] = {
OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"), OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"),
OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"), OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"),
OPT_END() OPT_END()
}; };
......
...@@ -463,7 +463,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -463,7 +463,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
builtin_help_subcommands, builtin_help_usage, 0); builtin_help_subcommands, builtin_help_usage, 0);
if (show_all) { if (show_all) {
printf("\n usage: %s\n\n", perf_usage_string); printf("\n Usage: %s\n\n", perf_usage_string);
list_commands("perf commands", &main_cmds, &other_cmds); list_commands("perf commands", &main_cmds, &other_cmds);
printf(" %s\n\n", perf_more_info_string); printf(" %s\n\n", perf_more_info_string);
return 0; return 0;
......
...@@ -686,7 +686,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, ...@@ -686,7 +686,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
set_print_ip_opts(&evsel->attr); set_print_ip_opts(&evsel->attr);
return perf_evsel__check_attr(evsel, scr->session); if (evsel->attr.sample_type)
err = perf_evsel__check_attr(evsel, scr->session);
return err;
} }
static int process_comm_event(struct perf_tool *tool, static int process_comm_event(struct perf_tool *tool,
......
...@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg) ...@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg)
static void print_noise(struct perf_evsel *evsel, double avg) static void print_noise(struct perf_evsel *evsel, double avg)
{ {
struct perf_stat *ps; struct perf_stat_evsel *ps;
if (run_count == 1) if (run_count == 1)
return; return;
...@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) ...@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
csv_sep); csv_sep);
break; break;
case AGGR_GLOBAL: case AGGR_GLOBAL:
case AGGR_UNSET:
default: default:
break; break;
} }
...@@ -671,7 +672,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix) ...@@ -671,7 +672,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
static void print_counter_aggr(struct perf_evsel *counter, char *prefix) static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
{ {
FILE *output = stat_config.output; FILE *output = stat_config.output;
struct perf_stat *ps = counter->priv; struct perf_stat_evsel *ps = counter->priv;
double avg = avg_stats(&ps->res_stats[0]); double avg = avg_stats(&ps->res_stats[0]);
int scaled = counter->counts->scaled; int scaled = counter->counts->scaled;
double uval; double uval;
...@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts) ...@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts)
case AGGR_GLOBAL: case AGGR_GLOBAL:
default: default:
fprintf(output, "# time counts %*s events\n", unit_width, "unit"); fprintf(output, "# time counts %*s events\n", unit_width, "unit");
case AGGR_UNSET:
break;
} }
} }
...@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) ...@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
evlist__for_each(evsel_list, counter) evlist__for_each(evsel_list, counter)
print_counter(counter, prefix); print_counter(counter, prefix);
break; break;
case AGGR_UNSET:
default: default:
break; break;
} }
...@@ -940,6 +944,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused, ...@@ -940,6 +944,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
return 0; return 0;
} }
static int perf_stat__get_socket(struct cpu_map *map, int cpu)
{
return cpu_map__get_socket(map, cpu, NULL);
}
static int perf_stat__get_core(struct cpu_map *map, int cpu)
{
return cpu_map__get_core(map, cpu, NULL);
}
static int perf_stat_init_aggr_mode(void) static int perf_stat_init_aggr_mode(void)
{ {
switch (stat_config.aggr_mode) { switch (stat_config.aggr_mode) {
...@@ -948,18 +962,19 @@ static int perf_stat_init_aggr_mode(void) ...@@ -948,18 +962,19 @@ static int perf_stat_init_aggr_mode(void)
perror("cannot build socket map"); perror("cannot build socket map");
return -1; return -1;
} }
aggr_get_id = cpu_map__get_socket; aggr_get_id = perf_stat__get_socket;
break; break;
case AGGR_CORE: case AGGR_CORE:
if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
perror("cannot build core map"); perror("cannot build core map");
return -1; return -1;
} }
aggr_get_id = cpu_map__get_core; aggr_get_id = perf_stat__get_core;
break; break;
case AGGR_NONE: case AGGR_NONE:
case AGGR_GLOBAL: case AGGR_GLOBAL:
case AGGR_THREAD: case AGGR_THREAD:
case AGGR_UNSET:
default: default:
break; break;
} }
......
...@@ -34,7 +34,7 @@ int test__openat_syscall_event_on_all_cpus(void) ...@@ -34,7 +34,7 @@ int test__openat_syscall_event_on_all_cpus(void)
evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
if (IS_ERR(evsel)) { if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf); pr_debug("%s\n", errbuf);
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -89,7 +89,7 @@ int test__syscall_openat_tp_fields(void) ...@@ -89,7 +89,7 @@ int test__syscall_openat_tp_fields(void)
err = perf_evsel__parse_sample(evsel, event, &sample); err = perf_evsel__parse_sample(evsel, event, &sample);
if (err) { if (err) {
pr_err("Can't parse sample, err = %d\n", err); pr_debug("Can't parse sample, err = %d\n", err);
goto out_delete_evlist; goto out_delete_evlist;
} }
......
...@@ -22,7 +22,7 @@ int test__openat_syscall_event(void) ...@@ -22,7 +22,7 @@ int test__openat_syscall_event(void)
evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
if (IS_ERR(evsel)) { if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf); pr_debug("%s\n", errbuf);
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include "tests.h" #include "tests.h"
#include "debug.h" #include "debug.h"
#include "util.h"
#include <linux/hw_breakpoint.h> #include <linux/hw_breakpoint.h>
#include <api/fs/fs.h> #include <api/fs/fs.h>
...@@ -1753,6 +1754,17 @@ static int test_pmu_events(void) ...@@ -1753,6 +1754,17 @@ static int test_pmu_events(void)
return ret; return ret;
} }
static void debug_warn(const char *warn, va_list params)
{
char msg[1024];
if (!verbose)
return;
vsnprintf(msg, sizeof(msg), warn, params);
fprintf(stderr, " Warning: %s\n", msg);
}
int test__parse_events(void) int test__parse_events(void)
{ {
int ret1, ret2 = 0; int ret1, ret2 = 0;
...@@ -1764,6 +1776,8 @@ do { \ ...@@ -1764,6 +1776,8 @@ do { \
ret2 = ret1; \ ret2 = ret1; \
} while (0) } while (0)
set_warning_routine(debug_warn);
TEST_EVENTS(test__events); TEST_EVENTS(test__events);
if (test_pmu()) if (test_pmu())
......
...@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map) ...@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
for (i = 0; i < map->nr; i++) { for (i = 0; i < map->nr; i++) {
TEST_ASSERT_VAL("Core ID doesn't match", TEST_ASSERT_VAL("Core ID doesn't match",
(session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i) & 0xffff))); (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
TEST_ASSERT_VAL("Socket ID doesn't match", TEST_ASSERT_VAL("Socket ID doesn't match",
(session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i))); (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
} }
perf_session__delete(session); perf_session__delete(session);
......
...@@ -241,7 +241,7 @@ int cpu_map__get_socket_id(int cpu) ...@@ -241,7 +241,7 @@ int cpu_map__get_socket_id(int cpu)
return ret ?: value; return ret ?: value;
} }
int cpu_map__get_socket(struct cpu_map *map, int idx) int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
{ {
int cpu; int cpu;
...@@ -258,8 +258,9 @@ static int cmp_ids(const void *a, const void *b) ...@@ -258,8 +258,9 @@ static int cmp_ids(const void *a, const void *b)
return *(int *)a - *(int *)b; return *(int *)a - *(int *)b;
} }
static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
int (*f)(struct cpu_map *map, int cpu)) int (*f)(struct cpu_map *map, int cpu, void *data),
void *data)
{ {
struct cpu_map *c; struct cpu_map *c;
int nr = cpus->nr; int nr = cpus->nr;
...@@ -271,7 +272,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, ...@@ -271,7 +272,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
return -1; return -1;
for (cpu = 0; cpu < nr; cpu++) { for (cpu = 0; cpu < nr; cpu++) {
s1 = f(cpus, cpu); s1 = f(cpus, cpu, data);
for (s2 = 0; s2 < c->nr; s2++) { for (s2 = 0; s2 < c->nr; s2++) {
if (s1 == c->map[s2]) if (s1 == c->map[s2])
break; break;
...@@ -295,7 +296,7 @@ int cpu_map__get_core_id(int cpu) ...@@ -295,7 +296,7 @@ int cpu_map__get_core_id(int cpu)
return ret ?: value; return ret ?: value;
} }
int cpu_map__get_core(struct cpu_map *map, int idx) int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
{ {
int cpu, s; int cpu, s;
...@@ -306,7 +307,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx) ...@@ -306,7 +307,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
cpu = cpu_map__get_core_id(cpu); cpu = cpu_map__get_core_id(cpu);
s = cpu_map__get_socket(map, idx); s = cpu_map__get_socket(map, idx, data);
if (s == -1) if (s == -1)
return -1; return -1;
...@@ -321,12 +322,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx) ...@@ -321,12 +322,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp) int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
{ {
return cpu_map__build_map(cpus, sockp, cpu_map__get_socket); return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL);
} }
int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep) int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
{ {
return cpu_map__build_map(cpus, corep, cpu_map__get_core); return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL);
} }
/* setup simple routines to easily access node numbers given a cpu number */ /* setup simple routines to easily access node numbers given a cpu number */
......
...@@ -19,9 +19,9 @@ struct cpu_map *cpu_map__dummy_new(void); ...@@ -19,9 +19,9 @@ struct cpu_map *cpu_map__dummy_new(void);
struct cpu_map *cpu_map__read(FILE *file); struct cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
int cpu_map__get_socket_id(int cpu); int cpu_map__get_socket_id(int cpu);
int cpu_map__get_socket(struct cpu_map *map, int idx); int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
int cpu_map__get_core_id(int cpu); int cpu_map__get_core_id(int cpu);
int cpu_map__get_core(struct cpu_map *map, int idx); int cpu_map__get_core(struct cpu_map *map, int idx, void *data);
int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
...@@ -87,4 +87,7 @@ static inline int cpu__get_node(int cpu) ...@@ -87,4 +87,7 @@ static inline int cpu__get_node(int cpu)
return cpunode_map[cpu]; return cpunode_map[cpu];
} }
int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
int (*f)(struct cpu_map *map, int cpu, void *data),
void *data);
#endif /* __PERF_CPUMAP_H */ #endif /* __PERF_CPUMAP_H */
...@@ -648,7 +648,7 @@ int usage_with_options_internal(const char * const *usagestr, ...@@ -648,7 +648,7 @@ int usage_with_options_internal(const char * const *usagestr,
if (!usagestr) if (!usagestr)
return PARSE_OPT_HELP; return PARSE_OPT_HELP;
fprintf(stderr, "\n usage: %s\n", *usagestr++); fprintf(stderr, "\n Usage: %s\n", *usagestr++);
while (*usagestr && **usagestr) while (*usagestr && **usagestr)
fprintf(stderr, " or: %s\n", *usagestr++); fprintf(stderr, " or: %s\n", *usagestr++);
while (*usagestr) { while (*usagestr) {
...@@ -684,7 +684,7 @@ int parse_options_usage(const char * const *usagestr, ...@@ -684,7 +684,7 @@ int parse_options_usage(const char * const *usagestr,
if (!usagestr) if (!usagestr)
goto opt; goto opt;
fprintf(stderr, "\n usage: %s\n", *usagestr++); fprintf(stderr, "\n Usage: %s\n", *usagestr++);
while (*usagestr && **usagestr) while (*usagestr && **usagestr)
fprintf(stderr, " or: %s\n", *usagestr++); fprintf(stderr, " or: %s\n", *usagestr++);
while (*usagestr) { while (*usagestr) {
......
...@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg) ...@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)
bool __perf_evsel_stat__is(struct perf_evsel *evsel, bool __perf_evsel_stat__is(struct perf_evsel *evsel,
enum perf_stat_evsel_id id) enum perf_stat_evsel_id id)
{ {
struct perf_stat *ps = evsel->priv; struct perf_stat_evsel *ps = evsel->priv;
return ps->id == id; return ps->id == id;
} }
...@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = { ...@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
void perf_stat_evsel_id_init(struct perf_evsel *evsel) void perf_stat_evsel_id_init(struct perf_evsel *evsel)
{ {
struct perf_stat *ps = evsel->priv; struct perf_stat_evsel *ps = evsel->priv;
int i; int i;
/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
...@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) ...@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
{ {
int i; int i;
struct perf_stat *ps = evsel->priv; struct perf_stat_evsel *ps = evsel->priv;
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
init_stats(&ps->res_stats[i]); init_stats(&ps->res_stats[i]);
...@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) ...@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
{ {
evsel->priv = zalloc(sizeof(struct perf_stat)); evsel->priv = zalloc(sizeof(struct perf_stat_evsel));
if (evsel->priv == NULL) if (evsel->priv == NULL)
return -ENOMEM; return -ENOMEM;
perf_evsel__reset_stat_priv(evsel); perf_evsel__reset_stat_priv(evsel);
...@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter, ...@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,
if (!(vals->run && vals->ena)) if (!(vals->run && vals->ena))
return 0; return 0;
s = cpu_map__get_socket(cpus, cpu); s = cpu_map__get_socket(cpus, cpu, NULL);
if (s < 0) if (s < 0)
return -1; return -1;
...@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel ...@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
aggr->ena += count->ena; aggr->ena += count->ena;
aggr->run += count->run; aggr->run += count->run;
} }
case AGGR_UNSET:
default: default:
break; break;
} }
...@@ -304,7 +305,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, ...@@ -304,7 +305,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
struct perf_evsel *counter) struct perf_evsel *counter)
{ {
struct perf_counts_values *aggr = &counter->counts->aggr; struct perf_counts_values *aggr = &counter->counts->aggr;
struct perf_stat *ps = counter->priv; struct perf_stat_evsel *ps = counter->priv;
u64 *count = counter->counts->aggr.values; u64 *count = counter->counts->aggr.values;
int i, ret; int i, ret;
......
...@@ -20,7 +20,7 @@ enum perf_stat_evsel_id { ...@@ -20,7 +20,7 @@ enum perf_stat_evsel_id {
PERF_STAT_EVSEL_ID__MAX, PERF_STAT_EVSEL_ID__MAX,
}; };
struct perf_stat { struct perf_stat_evsel {
struct stats res_stats[3]; struct stats res_stats[3];
enum perf_stat_evsel_id id; enum perf_stat_evsel_id id;
}; };
...@@ -31,6 +31,7 @@ enum aggr_mode { ...@@ -31,6 +31,7 @@ enum aggr_mode {
AGGR_SOCKET, AGGR_SOCKET,
AGGR_CORE, AGGR_CORE,
AGGR_THREAD, AGGR_THREAD,
AGGR_UNSET,
}; };
struct perf_stat_config { struct perf_stat_config {
......
...@@ -50,6 +50,11 @@ void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN) ...@@ -50,6 +50,11 @@ void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
die_routine = routine; die_routine = routine;
} }
void set_warning_routine(void (*routine)(const char *err, va_list params))
{
warn_routine = routine;
}
void usage(const char *err) void usage(const char *err)
{ {
usage_routine(err); usage_routine(err);
......
...@@ -145,6 +145,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) ...@@ -145,6 +145,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
extern void set_warning_routine(void (*routine)(const char *err, va_list params));
extern int prefixcmp(const char *str, const char *prefix); extern int prefixcmp(const char *str, const char *prefix);
extern void set_buildid_dir(const char *dir); extern void set_buildid_dir(const char *dir);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment