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
This commit is contained in:
commit
bce8fc4cb7
5 changed files with 65 additions and 30 deletions
|
@ -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,8 +3959,9 @@ 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 (perf_event_overflow(event, 0, &data, regs))
|
if (!(event->attr.exclude_idle && current->pid == 0))
|
||||||
ret = HRTIMER_NORESTART;
|
if (perf_event_overflow(event, 0, &data, regs))
|
||||||
|
ret = HRTIMER_NORESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
period = max_t(u64, 10000, event->hw.sample_period);
|
period = max_t(u64, 10000, event->hw.sample_period);
|
||||||
|
@ -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)
|
||||||
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)
|
||||||
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
|
||||||
# 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)
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
#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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue