diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-03-23 13:22:10 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-06 03:30:27 -0400 |
commit | 7b732a75047738e4f85438ed2f9cd34bf5f2a19a (patch) | |
tree | bae36de785ac819ceef6fa5e1b7884a4a421cc3c /include/linux | |
parent | b09d2501ed3d294619cbfbcf828ad39324d0e548 (diff) |
perf_counter: new output ABI - part 1
Impact: Rework the perfcounter output ABI
use sys_read() only for instant data and provide mmap() output for all
async overflow data.
The first mmap() determines the size of the output buffer. The mmap()
size must be a PAGE_SIZE multiple of 1+pages, where pages must be a
power of 2 or 0. Further mmap()s of the same fd must have the same
size. Once all maps are gone, you can again mmap() with a new size.
In case of 0 extra pages there is no data output and the first page
only contains meta data.
When there are data pages, a poll() event will be generated for each
full page of data. Furthermore, the output is circular. This means
that although 1 page is a valid configuration, its useless, since
we'll start overwriting it the instant we report a full page.
Future work will focus on the output format (currently maintained)
where we'll likey want each entry denoted by a header which includes a
type and length.
Further future work will allow to splice() the fd, also containing the
async overflow data -- splice() would be mutually exclusive with
mmap() of the data.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Orig-LKML-Reference: <20090323172417.470536358@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/perf_counter.h | 36 |
1 files changed, 15 insertions, 21 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 40b324e91bf6..2b5e66d5ebdf 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -152,6 +152,8 @@ struct perf_counter_mmap_page { | |||
152 | __u32 lock; /* seqlock for synchronization */ | 152 | __u32 lock; /* seqlock for synchronization */ |
153 | __u32 index; /* hardware counter identifier */ | 153 | __u32 index; /* hardware counter identifier */ |
154 | __s64 offset; /* add to hardware counter value */ | 154 | __s64 offset; /* add to hardware counter value */ |
155 | |||
156 | __u32 data_head; /* head in the data section */ | ||
155 | }; | 157 | }; |
156 | 158 | ||
157 | #ifdef __KERNEL__ | 159 | #ifdef __KERNEL__ |
@@ -218,21 +220,6 @@ struct hw_perf_counter { | |||
218 | #endif | 220 | #endif |
219 | }; | 221 | }; |
220 | 222 | ||
221 | /* | ||
222 | * Hardcoded buffer length limit for now, for IRQ-fed events: | ||
223 | */ | ||
224 | #define PERF_DATA_BUFLEN 2048 | ||
225 | |||
226 | /** | ||
227 | * struct perf_data - performance counter IRQ data sampling ... | ||
228 | */ | ||
229 | struct perf_data { | ||
230 | int len; | ||
231 | int rd_idx; | ||
232 | int overrun; | ||
233 | u8 data[PERF_DATA_BUFLEN]; | ||
234 | }; | ||
235 | |||
236 | struct perf_counter; | 223 | struct perf_counter; |
237 | 224 | ||
238 | /** | 225 | /** |
@@ -256,6 +243,14 @@ enum perf_counter_active_state { | |||
256 | 243 | ||
257 | struct file; | 244 | struct file; |
258 | 245 | ||
246 | struct perf_mmap_data { | ||
247 | struct rcu_head rcu_head; | ||
248 | int nr_pages; | ||
249 | atomic_t head; | ||
250 | struct perf_counter_mmap_page *user_page; | ||
251 | void *data_pages[0]; | ||
252 | }; | ||
253 | |||
259 | /** | 254 | /** |
260 | * struct perf_counter - performance counter kernel representation: | 255 | * struct perf_counter - performance counter kernel representation: |
261 | */ | 256 | */ |
@@ -289,16 +284,15 @@ struct perf_counter { | |||
289 | int oncpu; | 284 | int oncpu; |
290 | int cpu; | 285 | int cpu; |
291 | 286 | ||
292 | /* pointer to page shared with userspace via mmap */ | 287 | /* mmap bits */ |
293 | unsigned long user_page; | 288 | struct mutex mmap_mutex; |
289 | atomic_t mmap_count; | ||
290 | struct perf_mmap_data *data; | ||
294 | 291 | ||
295 | /* read() / irq related data */ | 292 | /* poll related */ |
296 | wait_queue_head_t waitq; | 293 | wait_queue_head_t waitq; |
297 | /* optional: for NMIs */ | 294 | /* optional: for NMIs */ |
298 | int wakeup_pending; | 295 | int wakeup_pending; |
299 | struct perf_data *irqdata; | ||
300 | struct perf_data *usrdata; | ||
301 | struct perf_data data[2]; | ||
302 | 296 | ||
303 | void (*destroy)(struct perf_counter *); | 297 | void (*destroy)(struct perf_counter *); |
304 | struct rcu_head rcu_head; | 298 | struct rcu_head rcu_head; |