aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/perf_counter.h
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2009-09-15 07:00:23 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-18 14:43:20 -0400
commit5622f295b53fb60dbf9bed3e2c89d182490a8b7f (patch)
tree8279554bddd1607d53dc06e97f4b5a1d0c085ccd /include/linux/perf_counter.h
parent4b77a7297795229eca96c41e1709a3c87909fabe (diff)
x86, perf_counter, bts: Optimize BTS overflow handling
Draining the BTS buffer on a buffer overflow interrupt takes too long resulting in a kernel lockup when tracing the kernel. Restructure perf_counter sampling into sample creation and sample output. Prepare a single reference sample for BTS sampling and update the from and to address fields when draining the BTS buffer. Drain the entire BTS buffer between a single perf_output_begin() / perf_output_end() pair. Signed-off-by: Markus Metzger <markus.t.metzger@intel.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20090915130023.A16204@sedona.ch.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/perf_counter.h')
-rw-r--r--include/linux/perf_counter.h68
1 files changed, 64 insertions, 4 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 6c1ef72ea501..c7375f97aa19 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -691,6 +691,17 @@ struct perf_cpu_context {
691 int recursion[4]; 691 int recursion[4];
692}; 692};
693 693
694struct perf_output_handle {
695 struct perf_counter *counter;
696 struct perf_mmap_data *data;
697 unsigned long head;
698 unsigned long offset;
699 int nmi;
700 int sample;
701 int locked;
702 unsigned long flags;
703};
704
694#ifdef CONFIG_PERF_COUNTERS 705#ifdef CONFIG_PERF_COUNTERS
695 706
696/* 707/*
@@ -722,16 +733,38 @@ extern int hw_perf_group_sched_in(struct perf_counter *group_leader,
722extern void perf_counter_update_userpage(struct perf_counter *counter); 733extern void perf_counter_update_userpage(struct perf_counter *counter);
723 734
724struct perf_sample_data { 735struct perf_sample_data {
725 struct pt_regs *regs; 736 u64 type;
737
738 u64 ip;
739 struct {
740 u32 pid;
741 u32 tid;
742 } tid_entry;
743 u64 time;
726 u64 addr; 744 u64 addr;
745 u64 id;
746 u64 stream_id;
747 struct {
748 u32 cpu;
749 u32 reserved;
750 } cpu_entry;
727 u64 period; 751 u64 period;
752 struct perf_callchain_entry *callchain;
728 struct perf_raw_record *raw; 753 struct perf_raw_record *raw;
729}; 754};
730 755
756extern void perf_output_sample(struct perf_output_handle *handle,
757 struct perf_event_header *header,
758 struct perf_sample_data *data,
759 struct perf_counter *counter);
760extern void perf_prepare_sample(struct perf_event_header *header,
761 struct perf_sample_data *data,
762 struct perf_counter *counter,
763 struct pt_regs *regs);
764
731extern int perf_counter_overflow(struct perf_counter *counter, int nmi, 765extern int perf_counter_overflow(struct perf_counter *counter, int nmi,
732 struct perf_sample_data *data); 766 struct perf_sample_data *data,
733extern void perf_counter_output(struct perf_counter *counter, int nmi, 767 struct pt_regs *regs);
734 struct perf_sample_data *data);
735 768
736/* 769/*
737 * Return 1 for a software counter, 0 for a hardware counter 770 * Return 1 for a software counter, 0 for a hardware counter
@@ -781,6 +814,12 @@ extern void perf_tpcounter_event(int event_id, u64 addr, u64 count,
781#define perf_instruction_pointer(regs) instruction_pointer(regs) 814#define perf_instruction_pointer(regs) instruction_pointer(regs)
782#endif 815#endif
783 816
817extern int perf_output_begin(struct perf_output_handle *handle,
818 struct perf_counter *counter, unsigned int size,
819 int nmi, int sample);
820extern void perf_output_end(struct perf_output_handle *handle);
821extern void perf_output_copy(struct perf_output_handle *handle,
822 const void *buf, unsigned int len);
784#else 823#else
785static inline void 824static inline void
786perf_counter_task_sched_in(struct task_struct *task, int cpu) { } 825perf_counter_task_sched_in(struct task_struct *task, int cpu) { }
@@ -807,7 +846,28 @@ static inline void perf_counter_mmap(struct vm_area_struct *vma) { }
807static inline void perf_counter_comm(struct task_struct *tsk) { } 846static inline void perf_counter_comm(struct task_struct *tsk) { }
808static inline void perf_counter_fork(struct task_struct *tsk) { } 847static inline void perf_counter_fork(struct task_struct *tsk) { }
809static inline void perf_counter_init(void) { } 848static inline void perf_counter_init(void) { }
849
850static inline int
851perf_output_begin(struct perf_output_handle *handle, struct perf_counter *c,
852 unsigned int size, int nmi, int sample) { }
853static inline void perf_output_end(struct perf_output_handle *handle) { }
854static inline void
855perf_output_copy(struct perf_output_handle *handle,
856 const void *buf, unsigned int len) { }
857static inline void
858perf_output_sample(struct perf_output_handle *handle,
859 struct perf_event_header *header,
860 struct perf_sample_data *data,
861 struct perf_counter *counter) { }
862static inline void
863perf_prepare_sample(struct perf_event_header *header,
864 struct perf_sample_data *data,
865 struct perf_counter *counter,
866 struct pt_regs *regs) { }
810#endif 867#endif
811 868
869#define perf_output_put(handle, x) \
870 perf_output_copy((handle), &(x), sizeof(x))
871
812#endif /* __KERNEL__ */ 872#endif /* __KERNEL__ */
813#endif /* _LINUX_PERF_COUNTER_H */ 873#endif /* _LINUX_PERF_COUNTER_H */