diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-05-01 06:23:16 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-01 07:23:43 -0400 |
commit | c33a0bc4e41ef169d6e807d8abb9502544b518e5 (patch) | |
tree | f7ba55205352cd91a4f86999710008e89932ef10 /include/linux/perf_counter.h | |
parent | 3c56999eec7acc105a31b4546c94aad2fb844b13 (diff) |
perf_counter: fix race in perf_output_*
When two (or more) contexts output to the same buffer, it is possible
to observe half written output.
Suppose we have CPU0 doing perf_counter_mmap(), CPU1 doing
perf_counter_overflow(). If CPU1 does a wakeup and exposes head to
user-space, then CPU2 can observe the data CPU0 is still writing.
[ Impact: fix occasionally corrupted profiling records ]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
LKML-Reference: <20090501102533.007821627@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/perf_counter.h')
-rw-r--r-- | include/linux/perf_counter.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 41aed4270057..f776851f8c4b 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -358,10 +358,13 @@ struct perf_mmap_data { | |||
358 | struct rcu_head rcu_head; | 358 | struct rcu_head rcu_head; |
359 | int nr_pages; /* nr of data pages */ | 359 | int nr_pages; /* nr of data pages */ |
360 | 360 | ||
361 | atomic_t wakeup; /* POLL_ for wakeups */ | 361 | atomic_t poll; /* POLL_ for wakeups */ |
362 | atomic_t head; /* write position */ | 362 | atomic_t head; /* write position */ |
363 | atomic_t events; /* event limit */ | 363 | atomic_t events; /* event limit */ |
364 | 364 | ||
365 | atomic_t wakeup_head; /* completed head */ | ||
366 | atomic_t lock; /* concurrent writes */ | ||
367 | |||
365 | struct perf_counter_mmap_page *user_page; | 368 | struct perf_counter_mmap_page *user_page; |
366 | void *data_pages[0]; | 369 | void *data_pages[0]; |
367 | }; | 370 | }; |