Commit bce8fc4c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-fixes-for-linus' of...

Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf tools: Remove -Wcast-align
  perf tools: Fix compatibility with libelf 0.8 and autodetect
  perf events: Don't generate events for the idle task when exclude_idle is set
  perf events: Fix swevent hrtimer sampling by keeping track of remaining time when enabling/disabling swevent hrtimers
parents a5e3013d ec29b8d2
...@@ -471,8 +471,8 @@ struct hw_perf_event { ...@@ -471,8 +471,8 @@ struct hw_perf_event {
unsigned long event_base; unsigned long event_base;
int idx; int idx;
}; };
union { /* software */ struct { /* software */
atomic64_t count; s64 remaining;
struct hrtimer hrtimer; struct hrtimer hrtimer;
}; };
}; };
......
...@@ -3959,6 +3959,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) ...@@ -3959,6 +3959,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
regs = task_pt_regs(current); regs = task_pt_regs(current);
if (regs) { if (regs) {
if (!(event->attr.exclude_idle && current->pid == 0))
if (perf_event_overflow(event, 0, &data, regs)) if (perf_event_overflow(event, 0, &data, regs))
ret = HRTIMER_NORESTART; ret = HRTIMER_NORESTART;
} }
...@@ -3969,6 +3970,42 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) ...@@ -3969,6 +3970,42 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
return ret; return ret;
} }
static void perf_swevent_start_hrtimer(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hwc->hrtimer.function = perf_swevent_hrtimer;
if (hwc->sample_period) {
u64 period;
if (hwc->remaining) {
if (hwc->remaining < 0)
period = 10000;
else
period = hwc->remaining;
hwc->remaining = 0;
} else {
period = max_t(u64, 10000, hwc->sample_period);
}
__hrtimer_start_range_ns(&hwc->hrtimer,
ns_to_ktime(period), 0,
HRTIMER_MODE_REL, 0);
}
}
static void perf_swevent_cancel_hrtimer(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
if (hwc->sample_period) {
ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
hwc->remaining = ktime_to_ns(remaining);
hrtimer_cancel(&hwc->hrtimer);
}
}
/* /*
* Software event: cpu wall time clock * Software event: cpu wall time clock
*/ */
...@@ -3991,22 +4028,14 @@ static int cpu_clock_perf_event_enable(struct perf_event *event) ...@@ -3991,22 +4028,14 @@ static int cpu_clock_perf_event_enable(struct perf_event *event)
int cpu = raw_smp_processor_id(); int cpu = raw_smp_processor_id();
atomic64_set(&hwc->prev_count, cpu_clock(cpu)); atomic64_set(&hwc->prev_count, cpu_clock(cpu));
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); perf_swevent_start_hrtimer(event);
hwc->hrtimer.function = perf_swevent_hrtimer;
if (hwc->sample_period) {
u64 period = max_t(u64, 10000, hwc->sample_period);
__hrtimer_start_range_ns(&hwc->hrtimer,
ns_to_ktime(period), 0,
HRTIMER_MODE_REL, 0);
}
return 0; return 0;
} }
static void cpu_clock_perf_event_disable(struct perf_event *event) static void cpu_clock_perf_event_disable(struct perf_event *event)
{ {
if (event->hw.sample_period) perf_swevent_cancel_hrtimer(event);
hrtimer_cancel(&event->hw.hrtimer);
cpu_clock_perf_event_update(event); cpu_clock_perf_event_update(event);
} }
...@@ -4043,22 +4072,15 @@ static int task_clock_perf_event_enable(struct perf_event *event) ...@@ -4043,22 +4072,15 @@ static int task_clock_perf_event_enable(struct perf_event *event)
now = event->ctx->time; now = event->ctx->time;
atomic64_set(&hwc->prev_count, now); atomic64_set(&hwc->prev_count, now);
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hwc->hrtimer.function = perf_swevent_hrtimer; perf_swevent_start_hrtimer(event);
if (hwc->sample_period) {
u64 period = max_t(u64, 10000, hwc->sample_period);
__hrtimer_start_range_ns(&hwc->hrtimer,
ns_to_ktime(period), 0,
HRTIMER_MODE_REL, 0);
}
return 0; return 0;
} }
static void task_clock_perf_event_disable(struct perf_event *event) static void task_clock_perf_event_disable(struct perf_event *event)
{ {
if (event->hw.sample_period) perf_swevent_cancel_hrtimer(event);
hrtimer_cancel(&event->hw.hrtimer);
task_clock_perf_event_update(event, event->ctx->time); task_clock_perf_event_update(event, event->ctx->time);
} }
......
...@@ -177,8 +177,7 @@ endif ...@@ -177,8 +177,7 @@ endif
# Include saner warnings here, which can catch bugs: # Include saner warnings here, which can catch bugs:
# #
EXTRA_WARNINGS := -Wcast-align EXTRA_WARNINGS := -Wformat
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
...@@ -422,7 +421,11 @@ ifeq ($(uname_S),Darwin) ...@@ -422,7 +421,11 @@ ifeq ($(uname_S),Darwin)
PTHREAD_LIBS = PTHREAD_LIBS =
endif endif
ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
BASIC_CFLAGS += -DLIBELF_NO_MMAP
endif
else
msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
endif endif
......
...@@ -413,7 +413,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v) ...@@ -413,7 +413,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
if (fd < 0) if (fd < 0)
goto out; goto out;
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) if (elf == NULL)
goto out_close; goto out_close;
...@@ -533,7 +533,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, ...@@ -533,7 +533,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
Elf *elf; Elf *elf;
int nr = 0, kernel = !strcmp("[kernel]", self->name); int nr = 0, kernel = !strcmp("[kernel]", self->name);
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) { if (elf == NULL) {
if (v) if (v)
fprintf(stderr, "%s: cannot read %s ELF file.\n", fprintf(stderr, "%s: cannot read %s ELF file.\n",
...@@ -675,7 +675,7 @@ static char *dso__read_build_id(struct dso *self, int v) ...@@ -675,7 +675,7 @@ static char *dso__read_build_id(struct dso *self, int v)
if (fd < 0) if (fd < 0)
goto out; goto out;
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) { if (elf == NULL) {
if (v) if (v)
fprintf(stderr, "%s: cannot read %s ELF file.\n", fprintf(stderr, "%s: cannot read %s ELF file.\n",
......
...@@ -27,6 +27,16 @@ static inline char *bfd_demangle(void __used *v, const char __used *c, ...@@ -27,6 +27,16 @@ static inline char *bfd_demangle(void __used *v, const char __used *c,
#endif #endif
#endif #endif
/*
* libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
* for newer versions we can use mmap to reduce memory usage:
*/
#ifdef LIBELF_NO_MMAP
# define PERF_ELF_C_READ_MMAP ELF_C_READ
#else
# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
#endif
#ifndef DMGL_PARAMS #ifndef DMGL_PARAMS
#define DMGL_PARAMS (1 << 0) /* Include function args */ #define DMGL_PARAMS (1 << 0) /* Include function args */
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
......
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