mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 09:31:14 +00:00
perf_counter: Allow for a wakeup watermark
Currently we wake the mmap() consumer once every PAGE_SIZE of data and/or once event wakeup_events when specified. For high speed sampling this results in too many wakeups wrt. the buffer size, hence change this. We move the default wakeup limit to 1/4-th the buffer size, and provide for means to manually specify this limit. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
850bc73ffc
commit
2667de81f3
2 changed files with 27 additions and 15 deletions
|
@ -199,10 +199,14 @@ struct perf_counter_attr {
|
||||||
inherit_stat : 1, /* per task counts */
|
inherit_stat : 1, /* per task counts */
|
||||||
enable_on_exec : 1, /* next exec enables */
|
enable_on_exec : 1, /* next exec enables */
|
||||||
task : 1, /* trace fork/exit */
|
task : 1, /* trace fork/exit */
|
||||||
|
watermark : 1, /* wakeup_watermark */
|
||||||
|
|
||||||
__reserved_1 : 50;
|
__reserved_1 : 49;
|
||||||
|
|
||||||
__u32 wakeup_events; /* wakeup every n events */
|
union {
|
||||||
|
__u32 wakeup_events; /* wakeup every n events */
|
||||||
|
__u32 wakeup_watermark; /* bytes before wakeup */
|
||||||
|
};
|
||||||
__u32 __reserved_2;
|
__u32 __reserved_2;
|
||||||
|
|
||||||
__u64 __reserved_3;
|
__u64 __reserved_3;
|
||||||
|
@ -521,6 +525,8 @@ struct perf_mmap_data {
|
||||||
atomic_t wakeup; /* needs a wakeup */
|
atomic_t wakeup; /* needs a wakeup */
|
||||||
atomic_t lost; /* nr records lost */
|
atomic_t lost; /* nr records lost */
|
||||||
|
|
||||||
|
long watermark; /* wakeup watermark */
|
||||||
|
|
||||||
struct perf_counter_mmap_page *user_page;
|
struct perf_counter_mmap_page *user_page;
|
||||||
void *data_pages[0];
|
void *data_pages[0];
|
||||||
};
|
};
|
||||||
|
|
|
@ -2176,6 +2176,13 @@ static int perf_mmap_data_alloc(struct perf_counter *counter, int nr_pages)
|
||||||
data->nr_pages = nr_pages;
|
data->nr_pages = nr_pages;
|
||||||
atomic_set(&data->lock, -1);
|
atomic_set(&data->lock, -1);
|
||||||
|
|
||||||
|
if (counter->attr.watermark) {
|
||||||
|
data->watermark = min_t(long, PAGE_SIZE * nr_pages,
|
||||||
|
counter->attr.wakeup_watermark);
|
||||||
|
}
|
||||||
|
if (!data->watermark)
|
||||||
|
data->watermark = max(PAGE_SIZE, PAGE_SIZE * nr_pages / 4);
|
||||||
|
|
||||||
rcu_assign_pointer(counter->data, data);
|
rcu_assign_pointer(counter->data, data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2517,23 +2524,15 @@ struct perf_output_handle {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool perf_output_space(struct perf_mmap_data *data,
|
static bool perf_output_space(struct perf_mmap_data *data, unsigned long tail,
|
||||||
unsigned int offset, unsigned int head)
|
unsigned long offset, unsigned long head)
|
||||||
{
|
{
|
||||||
unsigned long tail;
|
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
if (!data->writable)
|
if (!data->writable)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
mask = (data->nr_pages << PAGE_SHIFT) - 1;
|
mask = (data->nr_pages << PAGE_SHIFT) - 1;
|
||||||
/*
|
|
||||||
* Userspace could choose to issue a mb() before updating the tail
|
|
||||||
* pointer. So that all reads will be completed before the write is
|
|
||||||
* issued.
|
|
||||||
*/
|
|
||||||
tail = ACCESS_ONCE(data->user_page->data_tail);
|
|
||||||
smp_rmb();
|
|
||||||
|
|
||||||
offset = (offset - tail) & mask;
|
offset = (offset - tail) & mask;
|
||||||
head = (head - tail) & mask;
|
head = (head - tail) & mask;
|
||||||
|
@ -2679,7 +2678,7 @@ static int perf_output_begin(struct perf_output_handle *handle,
|
||||||
{
|
{
|
||||||
struct perf_counter *output_counter;
|
struct perf_counter *output_counter;
|
||||||
struct perf_mmap_data *data;
|
struct perf_mmap_data *data;
|
||||||
unsigned int offset, head;
|
unsigned long tail, offset, head;
|
||||||
int have_lost;
|
int have_lost;
|
||||||
struct {
|
struct {
|
||||||
struct perf_event_header header;
|
struct perf_event_header header;
|
||||||
|
@ -2717,16 +2716,23 @@ static int perf_output_begin(struct perf_output_handle *handle,
|
||||||
perf_output_lock(handle);
|
perf_output_lock(handle);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
/*
|
||||||
|
* Userspace could choose to issue a mb() before updating the
|
||||||
|
* tail pointer. So that all reads will be completed before the
|
||||||
|
* write is issued.
|
||||||
|
*/
|
||||||
|
tail = ACCESS_ONCE(data->user_page->data_tail);
|
||||||
|
smp_rmb();
|
||||||
offset = head = atomic_long_read(&data->head);
|
offset = head = atomic_long_read(&data->head);
|
||||||
head += size;
|
head += size;
|
||||||
if (unlikely(!perf_output_space(data, offset, head)))
|
if (unlikely(!perf_output_space(data, tail, offset, head)))
|
||||||
goto fail;
|
goto fail;
|
||||||
} while (atomic_long_cmpxchg(&data->head, offset, head) != offset);
|
} while (atomic_long_cmpxchg(&data->head, offset, head) != offset);
|
||||||
|
|
||||||
handle->offset = offset;
|
handle->offset = offset;
|
||||||
handle->head = head;
|
handle->head = head;
|
||||||
|
|
||||||
if ((offset >> PAGE_SHIFT) != (head >> PAGE_SHIFT))
|
if (head - tail > data->watermark)
|
||||||
atomic_set(&data->wakeup, 1);
|
atomic_set(&data->wakeup, 1);
|
||||||
|
|
||||||
if (have_lost) {
|
if (have_lost) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue