aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-12 07:49:45 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-14 14:30:49 -0500
commit9b51f66dcb09ac5eb6bc68fc111d5c7a1e0131d6 (patch)
treef7b3482ae284c214119efe309e356fb84de126bb /include
parentee06094f8279e1312fc0a31591320cc7b6f0ab1e (diff)
perfcounters: implement "counter inheritance"
Impact: implement new performance feature Counter inheritance can be used to run performance counters in a workload, transparently - and pipe back the counter results to the parent counter. Inheritance for performance counters works the following way: when creating a counter it can be marked with the .inherit=1 flag. Such counters are then 'inherited' by all child tasks (be they fork()-ed or clone()-ed). These counters get inherited through exec() boundaries as well (except through setuid boundaries). The counter values get added back to the parent counter(s) when the child task(s) exit - much like stime/utime statistics are gathered. So inherited counters are ideal to gather summary statistics about an application's behavior via shell commands, without having to modify that application. The timec.c command utilizes counter inheritance: http://redhat.com/~mingo/perfcounters/timec.c Sample output: $ ./timec -e 1 -e 3 -e 5 ls -lR /usr/include/ >/dev/null Performance counter stats for 'ls': 163516953 instructions 2295 cache-misses 2855182 branch-misses Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/linux/perf_counter.h24
1 files changed, 18 insertions, 6 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 72460289c654..e5d25bf8f74e 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -75,10 +75,11 @@ struct perf_counter_hw_event {
75 u64 irq_period; 75 u64 irq_period;
76 u32 record_type; 76 u32 record_type;
77 77
78 u32 disabled : 1, /* off by default */ 78 u32 disabled : 1, /* off by default */
79 nmi : 1, /* NMI sampling */ 79 nmi : 1, /* NMI sampling */
80 raw : 1, /* raw event type */ 80 raw : 1, /* raw event type */
81 __reserved_1 : 29; 81 inherit : 1, /* children inherit it */
82 __reserved_1 : 28;
82 83
83 u64 __reserved_2; 84 u64 __reserved_2;
84}; 85};
@@ -138,6 +139,8 @@ enum perf_counter_active_state {
138 PERF_COUNTER_STATE_ACTIVE = 1, 139 PERF_COUNTER_STATE_ACTIVE = 1,
139}; 140};
140 141
142struct file;
143
141/** 144/**
142 * struct perf_counter - performance counter kernel representation: 145 * struct perf_counter - performance counter kernel representation:
143 */ 146 */
@@ -156,7 +159,10 @@ struct perf_counter {
156 159
157 struct perf_counter_context *ctx; 160 struct perf_counter_context *ctx;
158 struct task_struct *task; 161 struct task_struct *task;
162 struct file *filp;
159 163
164 unsigned int nr_inherited;
165 struct perf_counter *parent;
160 /* 166 /*
161 * Protect attach/detach: 167 * Protect attach/detach:
162 */ 168 */
@@ -210,13 +216,16 @@ struct perf_cpu_context {
210extern int perf_max_counters; 216extern int perf_max_counters;
211 217
212#ifdef CONFIG_PERF_COUNTERS 218#ifdef CONFIG_PERF_COUNTERS
219extern void
220perf_counter_show(struct perf_counter *counter, char *str, int trace);
213extern const struct hw_perf_counter_ops * 221extern const struct hw_perf_counter_ops *
214hw_perf_counter_init(struct perf_counter *counter); 222hw_perf_counter_init(struct perf_counter *counter);
215 223
216extern void perf_counter_task_sched_in(struct task_struct *task, int cpu); 224extern void perf_counter_task_sched_in(struct task_struct *task, int cpu);
217extern void perf_counter_task_sched_out(struct task_struct *task, int cpu); 225extern void perf_counter_task_sched_out(struct task_struct *task, int cpu);
218extern void perf_counter_task_tick(struct task_struct *task, int cpu); 226extern void perf_counter_task_tick(struct task_struct *task, int cpu);
219extern void perf_counter_init_task(struct task_struct *task); 227extern void perf_counter_init_task(struct task_struct *child);
228extern void perf_counter_exit_task(struct task_struct *child);
220extern void perf_counter_notify(struct pt_regs *regs); 229extern void perf_counter_notify(struct pt_regs *regs);
221extern void perf_counter_print_debug(void); 230extern void perf_counter_print_debug(void);
222extern u64 hw_perf_save_disable(void); 231extern u64 hw_perf_save_disable(void);
@@ -226,12 +235,15 @@ extern int perf_counter_task_enable(void);
226 235
227#else 236#else
228static inline void 237static inline void
238perf_counter_show(struct perf_counter *counter, char *str, int trace) { }
239static inline void
229perf_counter_task_sched_in(struct task_struct *task, int cpu) { } 240perf_counter_task_sched_in(struct task_struct *task, int cpu) { }
230static inline void 241static inline void
231perf_counter_task_sched_out(struct task_struct *task, int cpu) { } 242perf_counter_task_sched_out(struct task_struct *task, int cpu) { }
232static inline void 243static inline void
233perf_counter_task_tick(struct task_struct *task, int cpu) { } 244perf_counter_task_tick(struct task_struct *task, int cpu) { }
234static inline void perf_counter_init_task(struct task_struct *task) { } 245static inline void perf_counter_init_task(struct task_struct *child) { }
246static inline void perf_counter_exit_task(struct task_struct *child) { }
235static inline void perf_counter_notify(struct pt_regs *regs) { } 247static inline void perf_counter_notify(struct pt_regs *regs) { }
236static inline void perf_counter_print_debug(void) { } 248static inline void perf_counter_print_debug(void) { }
237static inline void hw_perf_restore(u64 ctrl) { } 249static inline void hw_perf_restore(u64 ctrl) { }