Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/jolsa/perf into perf/core

Pull perf/core improvements and fixes from Jiri Olsa:

. Update attr test with PERF_FLAG_FD_CLOEXEC flag (Jiri Olsa)

. Enable close-on-exec flag on perf file descriptor (Yann Droneaud)

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Jul 18, 2014
2 parents ec6dbcb + fb57817 commit 2336ebc
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 14 deletions.
1 change: 1 addition & 0 deletions tools/perf/Makefile.perf
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ LIB_OBJS += $(OUTPUT)util/record.o
LIB_OBJS += $(OUTPUT)util/srcline.o
LIB_OBJS += $(OUTPUT)util/data.o
LIB_OBJS += $(OUTPUT)util/tsc.o
LIB_OBJS += $(OUTPUT)util/cloexec.o

LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/bench/mem-memcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#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"

Expand Down Expand Up @@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {

static void init_cycle(void)
{
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
perf_event_open_cloexec_flag());

if (cycle_fd < 0 && errno == ENOSYS)
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/bench/mem-memset.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "../util/util.h"
#include "../util/parse-options.h"
#include "../util/header.h"
#include "../util/cloexec.h"
#include "bench.h"
#include "mem-memset-arch.h"

Expand Down Expand Up @@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {

static void init_cycle(void)
{
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
perf_event_open_cloexec_flag());

if (cycle_fd < 0 && errno == ENOSYS)
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/builtin-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "util/header.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/cloexec.h"

#include "util/parse-options.h"
#include "util/trace-event.h"
Expand Down Expand Up @@ -434,7 +435,8 @@ static int self_open_counters(void)
attr.type = PERF_TYPE_SOFTWARE;
attr.config = PERF_COUNT_SW_TASK_CLOCK;

fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());

if (fd < 0)
pr_err("Error: sys_perf_event_open() syscall returned "
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/tests/attr/base-record
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[event]
fd=1
group_fd=-1
flags=0
# 0 or PERF_FLAG_FD_CLOEXEC flag
flags=0|8
cpu=*
type=0|1
size=96
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/tests/attr/base-stat
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[event]
fd=1
group_fd=-1
flags=0
# 0 or PERF_FLAG_FD_CLOEXEC flag
flags=0|8
cpu=*
type=0
size=96
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/bp_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "tests.h"
#include "debug.h"
#include "perf.h"
#include "cloexec.h"

static int fd1;
static int fd2;
Expand Down Expand Up @@ -78,7 +79,8 @@ static int bp_event(void *fn, int setup_signal)
pe.exclude_kernel = 1;
pe.exclude_hv = 1;

fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
fd = sys_perf_event_open(&pe, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_debug("failed opening event %llx\n", pe.config);
return TEST_FAIL;
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/bp_signal_overflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "tests.h"
#include "debug.h"
#include "perf.h"
#include "cloexec.h"

static int overflows;

Expand Down Expand Up @@ -91,7 +92,8 @@ int test__bp_signal_overflow(void)
pe.exclude_kernel = 1;
pe.exclude_hv = 1;

fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
fd = sys_perf_event_open(&pe, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_debug("failed opening event %llx\n", pe.config);
return TEST_FAIL;
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/rdpmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "perf.h"
#include "debug.h"
#include "tests.h"
#include "cloexec.h"

#if defined(__x86_64__) || defined(__i386__)

Expand Down Expand Up @@ -104,7 +105,8 @@ static int __test__rdpmc(void)
sa.sa_sigaction = segfault_handler;
sigaction(SIGSEGV, &sa, NULL);

fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_err("Error: sys_perf_event_open() syscall returned "
"with %d (%s)\n", fd, strerror(errno));
Expand Down
57 changes: 57 additions & 0 deletions tools/perf/util/cloexec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "util.h"
#include "../perf.h"
#include "cloexec.h"
#include "asm/bug.h"

static unsigned long flag = PERF_FLAG_FD_CLOEXEC;

static int perf_flag_probe(void)
{
/* use 'safest' configuration as used in perf_evsel__fallback() */
struct perf_event_attr attr = {
.type = PERF_COUNT_SW_CPU_CLOCK,
.config = PERF_COUNT_SW_CPU_CLOCK,
};
int fd;
int err;

/* check cloexec flag */
fd = sys_perf_event_open(&attr, 0, -1, -1,
PERF_FLAG_FD_CLOEXEC);
err = errno;

if (fd >= 0) {
close(fd);
return 1;
}

WARN_ONCE(err != EINVAL,
"perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
err, strerror(err));

/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
err = errno;

if (WARN_ONCE(fd < 0,
"perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
err, strerror(err)))
return -1;

close(fd);

return 0;
}

unsigned long perf_event_open_cloexec_flag(void)
{
static bool probed;

if (!probed) {
if (perf_flag_probe() <= 0)
flag = 0;
probed = true;
}

return flag;
}
6 changes: 6 additions & 0 deletions tools/perf/util/cloexec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef __PERF_CLOEXEC_H
#define __PERF_CLOEXEC_H

unsigned long perf_event_open_cloexec_flag(void);

#endif /* __PERF_CLOEXEC_H */
12 changes: 9 additions & 3 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static struct {
bool sample_id_all;
bool exclude_guest;
bool mmap2;
bool cloexec;
} perf_missing_features;

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
Expand Down Expand Up @@ -994,7 +995,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads)
{
int cpu, thread;
unsigned long flags = 0;
unsigned long flags = PERF_FLAG_FD_CLOEXEC;
int pid = -1, err;
enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;

Expand All @@ -1003,11 +1004,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
return -ENOMEM;

if (evsel->cgrp) {
flags = PERF_FLAG_PID_CGROUP;
flags |= PERF_FLAG_PID_CGROUP;
pid = evsel->cgrp->fd;
}

fallback_missing_features:
if (perf_missing_features.cloexec)
flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
if (perf_missing_features.mmap2)
evsel->attr.mmap2 = 0;
if (perf_missing_features.exclude_guest)
Expand Down Expand Up @@ -1076,7 +1079,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (err != -EINVAL || cpu > 0 || thread > 0)
goto out_close;

if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
perf_missing_features.cloexec = true;
goto fallback_missing_features;
} else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
perf_missing_features.mmap2 = true;
goto fallback_missing_features;
} else if (!perf_missing_features.exclude_guest &&
Expand Down
9 changes: 6 additions & 3 deletions tools/perf/util/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
#include "parse-events.h"
#include <api/fs/fs.h>
#include "util.h"
#include "cloexec.h"

typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);

static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
{
struct perf_evlist *evlist;
struct perf_evsel *evsel;
unsigned long flags = perf_event_open_cloexec_flag();
int err = -EAGAIN, fd;

evlist = perf_evlist__new();
Expand All @@ -22,14 +24,14 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)

evsel = perf_evlist__first(evlist);

fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
if (fd < 0)
goto out_delete;
close(fd);

fn(evsel);

fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
if (fd < 0) {
if (errno == EINVAL)
err = -EINVAL;
Expand Down Expand Up @@ -219,7 +221,8 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
cpu = evlist->cpus->map[0];
}

fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1,
perf_event_open_cloexec_flag());
if (fd >= 0) {
close(fd);
ret = true;
Expand Down

0 comments on commit 2336ebc

Please sign in to comment.