Commit 06c654ca 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 from Arnaldo Carvalho de Melo:

User visible changes:

  * Add --repeat global option to 'perf bench' to be used in benchmarks
    such as the existing 'futex' one, that was modified to use it instead
    of a local option. (Davidlohr Bueso)

  * Fix fd -> pathname resolution in 'trace', be it using /proc or
    a vfs_getname probe point. (Arnaldo Carvalho de Melo)

  * Add suggestion of how to set perf_event_paranoid sysctl, to help
    non-root users trying tools like 'trace' to get a working environment.
    (Arnaldo Carvalho de Melo)

Fixes:

  * Fix memory leak in the 'sched-messaging' perf bench test. (Davidlohr Bueso)

  * The -o and -n 'perf bench mem' options are mutually exclusive, emit error
    when both are specified. (Davidlohr Bueso)

  * Fix scrollbar refresh row index in the ui browser, problem exposed now
    that headers will be added and will be allowed to be switched on/off.
    (Jiri Olsa)

Cleanups:

  * Remove needless reassignments in 'trace' (Arnaldo Carvalho de Melo)

  * Cache the is_exit syscall test in 'trace) (Arnaldo Carvalho de Melo)

  * No need to reimplement err() in 'perf bench sched-messaging', drop barf().
    (Davidlohr Bueso).

  * Remove ev_name argument from perf_evsel__hists_browse, can be obtained
    from the other parameters. (Jiri Olsa)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 98d350cf ecdac968
......@@ -16,6 +16,10 @@ This 'perf bench' command is a general framework for benchmark suites.
COMMON OPTIONS
--------------
-r::
--repeat=::
Specify amount of times to repeat the run (default 10).
-f::
--format=::
Specify format style.
......
......@@ -43,5 +43,6 @@ extern int bench_futex_requeue(int argc, const char **argv, const char *prefix);
#define BENCH_FORMAT_UNKNOWN -1
extern int bench_format;
extern unsigned int bench_repeat;
#endif
......@@ -29,13 +29,6 @@ static u_int32_t futex1 = 0, futex2 = 0;
*/
static unsigned int nrequeue = 1;
/*
* There can be significant variance from run to run,
* the more repeats, the more exact the overall avg and
* the better idea of the futex latency.
*/
static unsigned int repeat = 10;
static pthread_t *worker;
static bool done = 0, silent = 0;
static pthread_mutex_t thread_lock;
......@@ -46,7 +39,6 @@ static unsigned int ncpus, threads_starting, nthreads = 0;
static const struct option options[] = {
OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
OPT_UINTEGER('r', "repeat", &repeat, "Specify amount of times to repeat the run"),
OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
OPT_END()
};
......@@ -146,7 +138,7 @@ int bench_futex_requeue(int argc, const char **argv,
pthread_cond_init(&thread_parent, NULL);
pthread_cond_init(&thread_worker, NULL);
for (j = 0; j < repeat && !done; j++) {
for (j = 0; j < bench_repeat && !done; j++) {
unsigned int nrequeued = 0;
struct timeval start, end, runtime;
......
......@@ -30,15 +30,8 @@ static u_int32_t futex1 = 0;
*/
static unsigned int nwakes = 1;
/*
* There can be significant variance from run to run,
* the more repeats, the more exact the overall avg and
* the better idea of the futex latency.
*/
static unsigned int repeat = 10;
pthread_t *worker;
static bool done = 0, silent = 0;
static bool done = false, silent = false;
static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker;
static struct stats waketime_stats, wakeup_stats;
......@@ -47,7 +40,6 @@ static unsigned int ncpus, threads_starting, nthreads = 0;
static const struct option options[] = {
OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
OPT_UINTEGER('r', "repeat", &repeat, "Specify amount of times to repeat the run"),
OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
OPT_END()
};
......@@ -149,7 +141,7 @@ int bench_futex_wake(int argc, const char **argv,
pthread_cond_init(&thread_parent, NULL);
pthread_cond_init(&thread_worker, NULL);
for (j = 0; j < repeat && !done; j++) {
for (j = 0; j < bench_repeat && !done; j++) {
unsigned int nwoken = 0;
struct timeval start, end, runtime;
......
......@@ -189,6 +189,11 @@ int bench_mem_memcpy(int argc, const char **argv,
argc = parse_options(argc, argv, options,
bench_mem_memcpy_usage, 0);
if (no_prefault && only_prefault) {
fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
return 1;
}
if (use_cycle)
init_cycle();
......
......@@ -181,6 +181,11 @@ int bench_mem_memset(int argc, const char **argv,
argc = parse_options(argc, argv, options,
bench_mem_memset_usage, 0);
if (no_prefault && only_prefault) {
fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
return 1;
}
if (use_cycle)
init_cycle();
......
......@@ -28,6 +28,7 @@
#include <sys/time.h>
#include <sys/poll.h>
#include <limits.h>
#include <err.h>
#define DATASIZE 100
......@@ -50,12 +51,6 @@ struct receiver_context {
int wakefd;
};
static void barf(const char *msg)
{
fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno));
exit(1);
}
static void fdpair(int fds[2])
{
if (use_pipes) {
......@@ -66,7 +61,7 @@ static void fdpair(int fds[2])
return;
}
barf(use_pipes ? "pipe()" : "socketpair()");
err(EXIT_FAILURE, use_pipes ? "pipe()" : "socketpair()");
}
/* Block until we're ready to go */
......@@ -77,11 +72,11 @@ static void ready(int ready_out, int wakefd)
/* Tell them we're ready. */
if (write(ready_out, &dummy, 1) != 1)
barf("CLIENT: ready write");
err(EXIT_FAILURE, "CLIENT: ready write");
/* Wait for "GO" signal */
if (poll(&pollfd, 1, -1) != 1)
barf("poll");
err(EXIT_FAILURE, "poll");
}
/* Sender sprays loops messages down each file descriptor */
......@@ -101,7 +96,7 @@ static void *sender(struct sender_context *ctx)
ret = write(ctx->out_fds[j], data + done,
sizeof(data)-done);
if (ret < 0)
barf("SENDER: write");
err(EXIT_FAILURE, "SENDER: write");
done += ret;
if (done < DATASIZE)
goto again;
......@@ -131,7 +126,7 @@ static void *receiver(struct receiver_context* ctx)
again:
ret = read(ctx->in_fds[0], data + done, DATASIZE - done);
if (ret < 0)
barf("SERVER: read");
err(EXIT_FAILURE, "SERVER: read");
done += ret;
if (done < DATASIZE)
goto again;
......@@ -144,14 +139,14 @@ static pthread_t create_worker(void *ctx, void *(*func)(void *))
{
pthread_attr_t attr;
pthread_t childid;
int err;
int ret;
if (!thread_mode) {
/* process mode */
/* Fork the receiver. */
switch (fork()) {
case -1:
barf("fork()");
err(EXIT_FAILURE, "fork()");
break;
case 0:
(*func) (ctx);
......@@ -165,19 +160,17 @@ static pthread_t create_worker(void *ctx, void *(*func)(void *))
}
if (pthread_attr_init(&attr) != 0)
barf("pthread_attr_init:");
err(EXIT_FAILURE, "pthread_attr_init:");
#ifndef __ia64__
if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
barf("pthread_attr_setstacksize");
err(EXIT_FAILURE, "pthread_attr_setstacksize");
#endif
err = pthread_create(&childid, &attr, func, ctx);
if (err != 0) {
fprintf(stderr, "pthread_create failed: %s (%d)\n",
strerror(err), err);
exit(-1);
}
ret = pthread_create(&childid, &attr, func, ctx);
if (ret != 0)
err(EXIT_FAILURE, "pthread_create failed");
return childid;
}
......@@ -207,14 +200,14 @@ static unsigned int group(pthread_t *pth,
+ num_fds * sizeof(int));
if (!snd_ctx)
barf("malloc()");
err(EXIT_FAILURE, "malloc()");
for (i = 0; i < num_fds; i++) {
int fds[2];
struct receiver_context *ctx = malloc(sizeof(*ctx));
if (!ctx)
barf("malloc()");
err(EXIT_FAILURE, "malloc()");
/* Create the pipe between client and server */
......@@ -281,7 +274,7 @@ int bench_sched_messaging(int argc, const char **argv,
pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t));
if (!pth_tab)
barf("main:malloc()");
err(EXIT_FAILURE, "main:malloc()");
fdpair(readyfds);
fdpair(wakefds);
......@@ -294,13 +287,13 @@ int bench_sched_messaging(int argc, const char **argv,
/* Wait for everyone to be ready */
for (i = 0; i < total_children; i++)
if (read(readyfds[0], &dummy, 1) != 1)
barf("Reading for readyfds");
err(EXIT_FAILURE, "Reading for readyfds");
gettimeofday(&start, NULL);
/* Kick them off */
if (write(wakefds[1], &dummy, 1) != 1)
barf("Writing to start them");
err(EXIT_FAILURE, "Writing to start them");
/* Reap them all */
for (i = 0; i < total_children; i++)
......@@ -332,5 +325,7 @@ int bench_sched_messaging(int argc, const char **argv,
break;
}
free(pth_tab);
return 0;
}
......@@ -104,9 +104,11 @@ static const char *bench_format_str;
/* Output/formatting style, exported to benchmark modules: */
int bench_format = BENCH_FORMAT_DEFAULT;
unsigned int bench_repeat = 10; /* default number of times to repeat the run */
static const struct option bench_options[] = {
OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"),
OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"),
OPT_END()
};
......@@ -226,6 +228,11 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
goto end;
}
if (bench_repeat == 0) {
printf("Invalid repeat option: Must specify a positive value\n");
goto end;
}
if (argc < 1) {
print_usage();
goto end;
......
......@@ -1108,6 +1108,7 @@ struct syscall {
struct event_format *tp_format;
const char *name;
bool filtered;
bool is_exit;
struct syscall_fmt *fmt;
size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
void **arg_parm;
......@@ -1276,11 +1277,11 @@ static const char *thread__fd_path(struct thread *thread, int fd,
if (fd < 0)
return NULL;
if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
if (!trace->live)
return NULL;
++trace->stats.proc_getname;
if (thread__read_fd_path(thread, fd)) {
if (thread__read_fd_path(thread, fd))
return NULL;
}
......@@ -1473,6 +1474,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
if (sc->tp_format == NULL)
return -1;
sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
return syscall__set_arg_fmts(sc);
}
......@@ -1629,7 +1632,6 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
return -1;
args = perf_evsel__sc_tp_ptr(evsel, args, sample);
ttrace = thread->priv;
if (ttrace->entry_str == NULL) {
ttrace->entry_str = malloc(1024);
......@@ -1644,7 +1646,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
args, trace, thread);
if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
if (sc->is_exit) {
if (!trace->duration_filter && !trace->summary_only) {
trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
fprintf(trace->output, "%-70s\n", ttrace->entry_str);
......@@ -1687,8 +1689,6 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
++trace->stats.vfs_getname;
}
ttrace = thread->priv;
ttrace->exit_time = sample->time;
if (ttrace->entry_time) {
......
......@@ -279,7 +279,7 @@ static void ui_browser__scrollbar_set(struct ui_browser *browser)
{
int height = browser->height, h = 0, pct = 0,
col = browser->width,
row = browser->y - 1;
row = 0;
if (browser->nr_entries > 1) {
pct = ((browser->index * (browser->height - 1)) /
......
......@@ -33,8 +33,7 @@ struct hist_browser {
extern void hist_browser__init_hpp(void);
static int hists__browser_title(struct hists *hists, char *bf, size_t size,
const char *ev_name);
static int hists__browser_title(struct hists *hists, char *bf, size_t size);
static void hist_browser__update_nr_entries(struct hist_browser *hb);
static struct rb_node *hists__filter_entries(struct rb_node *nd,
......@@ -346,7 +345,7 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
"Or reduce the sampling frequency.");
}
static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
static int hist_browser__run(struct hist_browser *browser,
struct hist_browser_timer *hbt)
{
int key;
......@@ -357,7 +356,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
browser->b.nr_entries = hist_browser__nr_entries(browser);
hist_browser__refresh_dimensions(browser);
hists__browser_title(browser->hists, title, sizeof(title), ev_name);
hists__browser_title(browser->hists, title, sizeof(title));
if (ui_browser__show(&browser->b, title,
"Press '?' for help on key bindings") < 0)
......@@ -384,7 +383,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
ui_browser__warn_lost_events(&browser->b);
}
hists__browser_title(browser->hists, title, sizeof(title), ev_name);
hists__browser_title(browser->hists, title, sizeof(title));
ui_browser__show_title(&browser->b, title);
continue;
}
......@@ -1213,8 +1212,7 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
return browser->he_selection->thread;
}
static int hists__browser_title(struct hists *hists, char *bf, size_t size,
const char *ev_name)
static int hists__browser_title(struct hists *hists, char *bf, size_t size)
{
char unit;
int printed;
......@@ -1223,6 +1221,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
u64 nr_events = hists->stats.total_period;
struct perf_evsel *evsel = hists_to_evsel(hists);
const char *ev_name = perf_evsel__name(evsel);
char buf[512];
size_t buflen = sizeof(buf);
......@@ -1390,7 +1389,7 @@ static void hist_browser__update_nr_entries(struct hist_browser *hb)
}
static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
const char *helpline, const char *ev_name,
const char *helpline,
bool left_exits,
struct hist_browser_timer *hbt,
float min_pcnt,
......@@ -1465,7 +1464,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
nr_options = 0;
key = hist_browser__run(browser, ev_name, hbt);
key = hist_browser__run(browser, hbt);
if (browser->he_selection != NULL) {
thread = hist_browser__selected_thread(browser);
......@@ -1843,7 +1842,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
{
struct perf_evlist *evlist = menu->b.priv;
struct perf_evsel *pos;
const char *ev_name, *title = "Available samples";
const char *title = "Available samples";
int delay_secs = hbt ? hbt->refresh : 0;
int key;
......@@ -1876,9 +1875,8 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
*/
if (hbt)
hbt->timer(hbt->arg);
ev_name = perf_evsel__name(pos);
key = perf_evsel__hists_browse(pos, nr_events, help,
ev_name, true, hbt,
true, hbt,
menu->min_pcnt,
menu->env);
ui_browser__show_title(&menu->b, title);
......@@ -1982,10 +1980,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
single_entry:
if (nr_entries == 1) {
struct perf_evsel *first = perf_evlist__first(evlist);
const char *ev_name = perf_evsel__name(first);
return perf_evsel__hists_browse(first, nr_entries, help,
ev_name, false, hbt, min_pcnt,
false, hbt, min_pcnt,
env);
}
......
......@@ -1214,10 +1214,11 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
"For your workloads it needs to be <= 1\nHint:\t");
}
printed += scnprintf(buf + printed, size - printed,
"For system wide tracing it needs to be set to -1");
"For system wide tracing it needs to be set to -1.\n");
printed += scnprintf(buf + printed, size - printed,
".\nHint:\tThe current value is %d.", value);
"Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n"
"Hint:\tThe current value is %d.", value);
break;
default:
scnprintf(buf, size, "%s", emsg);
......
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