diff options
Diffstat (limited to 'kernel/events/ring_buffer.c')
-rw-r--r-- | kernel/events/ring_buffer.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 67b328337a41..232f00f273cb 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
@@ -296,6 +296,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, | |||
296 | */ | 296 | */ |
297 | if (!rb->aux_overwrite) { | 297 | if (!rb->aux_overwrite) { |
298 | aux_tail = ACCESS_ONCE(rb->user_page->aux_tail); | 298 | aux_tail = ACCESS_ONCE(rb->user_page->aux_tail); |
299 | handle->wakeup = local_read(&rb->aux_wakeup) + rb->aux_watermark; | ||
299 | if (aux_head - aux_tail < perf_aux_size(rb)) | 300 | if (aux_head - aux_tail < perf_aux_size(rb)) |
300 | handle->size = CIRC_SPACE(aux_head, aux_tail, perf_aux_size(rb)); | 301 | handle->size = CIRC_SPACE(aux_head, aux_tail, perf_aux_size(rb)); |
301 | 302 | ||
@@ -359,9 +360,12 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, | |||
359 | perf_event_aux_event(handle->event, aux_head, size, flags); | 360 | perf_event_aux_event(handle->event, aux_head, size, flags); |
360 | } | 361 | } |
361 | 362 | ||
362 | rb->user_page->aux_head = local_read(&rb->aux_head); | 363 | aux_head = rb->user_page->aux_head = local_read(&rb->aux_head); |
363 | 364 | ||
364 | perf_output_wakeup(handle); | 365 | if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) { |
366 | perf_output_wakeup(handle); | ||
367 | local_add(rb->aux_watermark, &rb->aux_wakeup); | ||
368 | } | ||
365 | handle->event = NULL; | 369 | handle->event = NULL; |
366 | 370 | ||
367 | local_set(&rb->aux_nest, 0); | 371 | local_set(&rb->aux_nest, 0); |
@@ -383,6 +387,14 @@ int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size) | |||
383 | 387 | ||
384 | local_add(size, &rb->aux_head); | 388 | local_add(size, &rb->aux_head); |
385 | 389 | ||
390 | aux_head = rb->user_page->aux_head = local_read(&rb->aux_head); | ||
391 | if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) { | ||
392 | perf_output_wakeup(handle); | ||
393 | local_add(rb->aux_watermark, &rb->aux_wakeup); | ||
394 | handle->wakeup = local_read(&rb->aux_wakeup) + | ||
395 | rb->aux_watermark; | ||
396 | } | ||
397 | |||
386 | handle->head = aux_head; | 398 | handle->head = aux_head; |
387 | handle->size -= size; | 399 | handle->size -= size; |
388 | 400 | ||
@@ -433,7 +445,7 @@ static void rb_free_aux_page(struct ring_buffer *rb, int idx) | |||
433 | } | 445 | } |
434 | 446 | ||
435 | int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event, | 447 | int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event, |
436 | pgoff_t pgoff, int nr_pages, int flags) | 448 | pgoff_t pgoff, int nr_pages, long watermark, int flags) |
437 | { | 449 | { |
438 | bool overwrite = !(flags & RING_BUFFER_WRITABLE); | 450 | bool overwrite = !(flags & RING_BUFFER_WRITABLE); |
439 | int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu); | 451 | int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu); |
@@ -497,6 +509,10 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event, | |||
497 | atomic_set(&rb->aux_refcount, 1); | 509 | atomic_set(&rb->aux_refcount, 1); |
498 | 510 | ||
499 | rb->aux_overwrite = overwrite; | 511 | rb->aux_overwrite = overwrite; |
512 | rb->aux_watermark = watermark; | ||
513 | |||
514 | if (!rb->aux_watermark && !rb->aux_overwrite) | ||
515 | rb->aux_watermark = nr_pages << (PAGE_SHIFT - 1); | ||
500 | 516 | ||
501 | out: | 517 | out: |
502 | if (!ret) | 518 | if (!ret) |