diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-12 07:49:45 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-14 14:30:49 -0500 |
commit | 9b51f66dcb09ac5eb6bc68fc111d5c7a1e0131d6 (patch) | |
tree | f7b3482ae284c214119efe309e356fb84de126bb /include | |
parent | ee06094f8279e1312fc0a31591320cc7b6f0ab1e (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.h | 24 |
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 | ||
142 | struct 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 { | |||
210 | extern int perf_max_counters; | 216 | extern int perf_max_counters; |
211 | 217 | ||
212 | #ifdef CONFIG_PERF_COUNTERS | 218 | #ifdef CONFIG_PERF_COUNTERS |
219 | extern void | ||
220 | perf_counter_show(struct perf_counter *counter, char *str, int trace); | ||
213 | extern const struct hw_perf_counter_ops * | 221 | extern const struct hw_perf_counter_ops * |
214 | hw_perf_counter_init(struct perf_counter *counter); | 222 | hw_perf_counter_init(struct perf_counter *counter); |
215 | 223 | ||
216 | extern void perf_counter_task_sched_in(struct task_struct *task, int cpu); | 224 | extern void perf_counter_task_sched_in(struct task_struct *task, int cpu); |
217 | extern void perf_counter_task_sched_out(struct task_struct *task, int cpu); | 225 | extern void perf_counter_task_sched_out(struct task_struct *task, int cpu); |
218 | extern void perf_counter_task_tick(struct task_struct *task, int cpu); | 226 | extern void perf_counter_task_tick(struct task_struct *task, int cpu); |
219 | extern void perf_counter_init_task(struct task_struct *task); | 227 | extern void perf_counter_init_task(struct task_struct *child); |
228 | extern void perf_counter_exit_task(struct task_struct *child); | ||
220 | extern void perf_counter_notify(struct pt_regs *regs); | 229 | extern void perf_counter_notify(struct pt_regs *regs); |
221 | extern void perf_counter_print_debug(void); | 230 | extern void perf_counter_print_debug(void); |
222 | extern u64 hw_perf_save_disable(void); | 231 | extern u64 hw_perf_save_disable(void); |
@@ -226,12 +235,15 @@ extern int perf_counter_task_enable(void); | |||
226 | 235 | ||
227 | #else | 236 | #else |
228 | static inline void | 237 | static inline void |
238 | perf_counter_show(struct perf_counter *counter, char *str, int trace) { } | ||
239 | static inline void | ||
229 | perf_counter_task_sched_in(struct task_struct *task, int cpu) { } | 240 | perf_counter_task_sched_in(struct task_struct *task, int cpu) { } |
230 | static inline void | 241 | static inline void |
231 | perf_counter_task_sched_out(struct task_struct *task, int cpu) { } | 242 | perf_counter_task_sched_out(struct task_struct *task, int cpu) { } |
232 | static inline void | 243 | static inline void |
233 | perf_counter_task_tick(struct task_struct *task, int cpu) { } | 244 | perf_counter_task_tick(struct task_struct *task, int cpu) { } |
234 | static inline void perf_counter_init_task(struct task_struct *task) { } | 245 | static inline void perf_counter_init_task(struct task_struct *child) { } |
246 | static inline void perf_counter_exit_task(struct task_struct *child) { } | ||
235 | static inline void perf_counter_notify(struct pt_regs *regs) { } | 247 | static inline void perf_counter_notify(struct pt_regs *regs) { } |
236 | static inline void perf_counter_print_debug(void) { } | 248 | static inline void perf_counter_print_debug(void) { } |
237 | static inline void hw_perf_restore(u64 ctrl) { } | 249 | static inline void hw_perf_restore(u64 ctrl) { } |