diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-12-05 03:44:31 -0500 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-12-06 02:27:18 -0500 |
| commit | b326e9560a28fc3e950637ef51847ed8f05c1335 (patch) | |
| tree | 0804c8c4f28d4ae152d5e9205ce5a958f0d26b79 /include/linux | |
| parent | 2f0993e0fb663c49e4d1e02654f6203246be4817 (diff) | |
hw-breakpoints: Use overflow handler instead of the event callback
struct perf_event::event callback was called when a breakpoint
triggers. But this is a rather opaque callback, pretty
tied-only to the breakpoint API and not really integrated into perf
as it triggers even when we don't overflow.
We prefer to use overflow_handler() as it fits into the perf events
rules, being called only when we overflow.
Reported-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: "K. Prasad" <prasad@linux.vnet.ibm.com>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/hw_breakpoint.h | 25 | ||||
| -rw-r--r-- | include/linux/perf_event.h | 13 |
2 files changed, 18 insertions, 20 deletions
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h index d33096e0dbd4..4d14a384a01e 100644 --- a/include/linux/hw_breakpoint.h +++ b/include/linux/hw_breakpoint.h | |||
| @@ -20,19 +20,16 @@ enum { | |||
| 20 | 20 | ||
| 21 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | 21 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
| 22 | 22 | ||
| 23 | /* As it's for in-kernel or ptrace use, we want it to be pinned */ | ||
| 24 | #define DEFINE_BREAKPOINT_ATTR(name) \ | ||
| 25 | struct perf_event_attr name = { \ | ||
| 26 | .type = PERF_TYPE_BREAKPOINT, \ | ||
| 27 | .size = sizeof(name), \ | ||
| 28 | .pinned = 1, \ | ||
| 29 | }; | ||
| 30 | |||
| 31 | static inline void hw_breakpoint_init(struct perf_event_attr *attr) | 23 | static inline void hw_breakpoint_init(struct perf_event_attr *attr) |
| 32 | { | 24 | { |
| 33 | attr->type = PERF_TYPE_BREAKPOINT; | 25 | attr->type = PERF_TYPE_BREAKPOINT; |
| 34 | attr->size = sizeof(*attr); | 26 | attr->size = sizeof(*attr); |
| 27 | /* | ||
| 28 | * As it's for in-kernel or ptrace use, we want it to be pinned | ||
| 29 | * and to call its callback every hits. | ||
| 30 | */ | ||
| 35 | attr->pinned = 1; | 31 | attr->pinned = 1; |
| 32 | attr->sample_period = 1; | ||
| 36 | } | 33 | } |
| 37 | 34 | ||
| 38 | static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) | 35 | static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) |
| @@ -52,7 +49,7 @@ static inline int hw_breakpoint_len(struct perf_event *bp) | |||
| 52 | 49 | ||
| 53 | extern struct perf_event * | 50 | extern struct perf_event * |
| 54 | register_user_hw_breakpoint(struct perf_event_attr *attr, | 51 | register_user_hw_breakpoint(struct perf_event_attr *attr, |
| 55 | perf_callback_t triggered, | 52 | perf_overflow_handler_t triggered, |
| 56 | struct task_struct *tsk); | 53 | struct task_struct *tsk); |
| 57 | 54 | ||
| 58 | /* FIXME: only change from the attr, and don't unregister */ | 55 | /* FIXME: only change from the attr, and don't unregister */ |
| @@ -64,12 +61,12 @@ modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); | |||
| 64 | */ | 61 | */ |
| 65 | extern struct perf_event * | 62 | extern struct perf_event * |
| 66 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, | 63 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, |
| 67 | perf_callback_t triggered, | 64 | perf_overflow_handler_t triggered, |
| 68 | int cpu); | 65 | int cpu); |
| 69 | 66 | ||
| 70 | extern struct perf_event ** | 67 | extern struct perf_event ** |
| 71 | register_wide_hw_breakpoint(struct perf_event_attr *attr, | 68 | register_wide_hw_breakpoint(struct perf_event_attr *attr, |
| 72 | perf_callback_t triggered); | 69 | perf_overflow_handler_t triggered); |
| 73 | 70 | ||
| 74 | extern int register_perf_hw_breakpoint(struct perf_event *bp); | 71 | extern int register_perf_hw_breakpoint(struct perf_event *bp); |
| 75 | extern int __register_perf_hw_breakpoint(struct perf_event *bp); | 72 | extern int __register_perf_hw_breakpoint(struct perf_event *bp); |
| @@ -90,18 +87,18 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp) | |||
| 90 | 87 | ||
| 91 | static inline struct perf_event * | 88 | static inline struct perf_event * |
| 92 | register_user_hw_breakpoint(struct perf_event_attr *attr, | 89 | register_user_hw_breakpoint(struct perf_event_attr *attr, |
| 93 | perf_callback_t triggered, | 90 | perf_overflow_handler_t triggered, |
| 94 | struct task_struct *tsk) { return NULL; } | 91 | struct task_struct *tsk) { return NULL; } |
| 95 | static inline struct perf_event * | 92 | static inline struct perf_event * |
| 96 | modify_user_hw_breakpoint(struct perf_event *bp, | 93 | modify_user_hw_breakpoint(struct perf_event *bp, |
| 97 | struct perf_event_attr *attr) { return NULL; } | 94 | struct perf_event_attr *attr) { return NULL; } |
| 98 | static inline struct perf_event * | 95 | static inline struct perf_event * |
| 99 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, | 96 | register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, |
| 100 | perf_callback_t triggered, | 97 | perf_overflow_handler_t triggered, |
| 101 | int cpu) { return NULL; } | 98 | int cpu) { return NULL; } |
| 102 | static inline struct perf_event ** | 99 | static inline struct perf_event ** |
| 103 | register_wide_hw_breakpoint(struct perf_event_attr *attr, | 100 | register_wide_hw_breakpoint(struct perf_event_attr *attr, |
| 104 | perf_callback_t triggered) { return NULL; } | 101 | perf_overflow_handler_t triggered) { return NULL; } |
| 105 | static inline int | 102 | static inline int |
| 106 | register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } | 103 | register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } |
| 107 | static inline int | 104 | static inline int |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 84bd28a0ffab..d2f2667430da 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -565,10 +565,13 @@ struct perf_pending_entry { | |||
| 565 | void (*func)(struct perf_pending_entry *); | 565 | void (*func)(struct perf_pending_entry *); |
| 566 | }; | 566 | }; |
| 567 | 567 | ||
| 568 | typedef void (*perf_callback_t)(struct perf_event *, void *); | ||
| 569 | |||
| 570 | struct perf_sample_data; | 568 | struct perf_sample_data; |
| 571 | 569 | ||
| 570 | typedef void (*perf_callback_t)(struct perf_event *, void *); | ||
| 571 | typedef void (*perf_overflow_handler_t)(struct perf_event *, int, | ||
| 572 | struct perf_sample_data *, | ||
| 573 | struct pt_regs *regs); | ||
| 574 | |||
| 572 | /** | 575 | /** |
| 573 | * struct perf_event - performance event kernel representation: | 576 | * struct perf_event - performance event kernel representation: |
| 574 | */ | 577 | */ |
| @@ -660,9 +663,7 @@ struct perf_event { | |||
| 660 | struct pid_namespace *ns; | 663 | struct pid_namespace *ns; |
| 661 | u64 id; | 664 | u64 id; |
| 662 | 665 | ||
| 663 | void (*overflow_handler)(struct perf_event *event, | 666 | perf_overflow_handler_t overflow_handler; |
| 664 | int nmi, struct perf_sample_data *data, | ||
| 665 | struct pt_regs *regs); | ||
| 666 | 667 | ||
| 667 | #ifdef CONFIG_EVENT_PROFILE | 668 | #ifdef CONFIG_EVENT_PROFILE |
| 668 | struct event_filter *filter; | 669 | struct event_filter *filter; |
| @@ -779,7 +780,7 @@ extern struct perf_event * | |||
| 779 | perf_event_create_kernel_counter(struct perf_event_attr *attr, | 780 | perf_event_create_kernel_counter(struct perf_event_attr *attr, |
| 780 | int cpu, | 781 | int cpu, |
| 781 | pid_t pid, | 782 | pid_t pid, |
| 782 | perf_callback_t callback); | 783 | perf_overflow_handler_t callback); |
| 783 | extern u64 perf_event_read_value(struct perf_event *event, | 784 | extern u64 perf_event_read_value(struct perf_event *event, |
| 784 | u64 *enabled, u64 *running); | 785 | u64 *enabled, u64 *running); |
| 785 | 786 | ||
