diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 2d75c94ae87d..a56e07c8d15b 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -538,16 +538,18 @@ static void rb_wake_up_waiters(struct irq_work *work) | |||
538 | * ring_buffer_wait - wait for input to the ring buffer | 538 | * ring_buffer_wait - wait for input to the ring buffer |
539 | * @buffer: buffer to wait on | 539 | * @buffer: buffer to wait on |
540 | * @cpu: the cpu buffer to wait on | 540 | * @cpu: the cpu buffer to wait on |
541 | * @full: wait until a full page is available, if @cpu != RING_BUFFER_ALL_CPUS | ||
541 | * | 542 | * |
542 | * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon | 543 | * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon |
543 | * as data is added to any of the @buffer's cpu buffers. Otherwise | 544 | * as data is added to any of the @buffer's cpu buffers. Otherwise |
544 | * it will wait for data to be added to a specific cpu buffer. | 545 | * it will wait for data to be added to a specific cpu buffer. |
545 | */ | 546 | */ |
546 | int ring_buffer_wait(struct ring_buffer *buffer, int cpu) | 547 | int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full) |
547 | { | 548 | { |
548 | struct ring_buffer_per_cpu *cpu_buffer; | 549 | struct ring_buffer_per_cpu *uninitialized_var(cpu_buffer); |
549 | DEFINE_WAIT(wait); | 550 | DEFINE_WAIT(wait); |
550 | struct rb_irq_work *work; | 551 | struct rb_irq_work *work; |
552 | int ret = 0; | ||
551 | 553 | ||
552 | /* | 554 | /* |
553 | * Depending on what the caller is waiting for, either any | 555 | * Depending on what the caller is waiting for, either any |
@@ -564,36 +566,61 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu) | |||
564 | } | 566 | } |
565 | 567 | ||
566 | 568 | ||
567 | prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE); | 569 | while (true) { |
570 | prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE); | ||
568 | 571 | ||
569 | /* | 572 | /* |
570 | * The events can happen in critical sections where | 573 | * The events can happen in critical sections where |
571 | * checking a work queue can cause deadlocks. | 574 | * checking a work queue can cause deadlocks. |
572 | * After adding a task to the queue, this flag is set | 575 | * After adding a task to the queue, this flag is set |
573 | * only to notify events to try to wake up the queue | 576 | * only to notify events to try to wake up the queue |
574 | * using irq_work. | 577 | * using irq_work. |
575 | * | 578 | * |
576 | * We don't clear it even if the buffer is no longer | 579 | * We don't clear it even if the buffer is no longer |
577 | * empty. The flag only causes the next event to run | 580 | * empty. The flag only causes the next event to run |
578 | * irq_work to do the work queue wake up. The worse | 581 | * irq_work to do the work queue wake up. The worse |
579 | * that can happen if we race with !trace_empty() is that | 582 | * that can happen if we race with !trace_empty() is that |
580 | * an event will cause an irq_work to try to wake up | 583 | * an event will cause an irq_work to try to wake up |
581 | * an empty queue. | 584 | * an empty queue. |
582 | * | 585 | * |
583 | * There's no reason to protect this flag either, as | 586 | * There's no reason to protect this flag either, as |
584 | * the work queue and irq_work logic will do the necessary | 587 | * the work queue and irq_work logic will do the necessary |
585 | * synchronization for the wake ups. The only thing | 588 | * synchronization for the wake ups. The only thing |
586 | * that is necessary is that the wake up happens after | 589 | * that is necessary is that the wake up happens after |
587 | * a task has been queued. It's OK for spurious wake ups. | 590 | * a task has been queued. It's OK for spurious wake ups. |
588 | */ | 591 | */ |
589 | work->waiters_pending = true; | 592 | work->waiters_pending = true; |
593 | |||
594 | if (signal_pending(current)) { | ||
595 | ret = -EINTR; | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | if (cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) | ||
600 | break; | ||
601 | |||
602 | if (cpu != RING_BUFFER_ALL_CPUS && | ||
603 | !ring_buffer_empty_cpu(buffer, cpu)) { | ||
604 | unsigned long flags; | ||
605 | bool pagebusy; | ||
606 | |||
607 | if (!full) | ||
608 | break; | ||
609 | |||
610 | raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags); | ||
611 | pagebusy = cpu_buffer->reader_page == cpu_buffer->commit_page; | ||
612 | raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | ||
613 | |||
614 | if (!pagebusy) | ||
615 | break; | ||
616 | } | ||
590 | 617 | ||
591 | if ((cpu == RING_BUFFER_ALL_CPUS && ring_buffer_empty(buffer)) || | ||
592 | (cpu != RING_BUFFER_ALL_CPUS && ring_buffer_empty_cpu(buffer, cpu))) | ||
593 | schedule(); | 618 | schedule(); |
619 | } | ||
594 | 620 | ||
595 | finish_wait(&work->waiters, &wait); | 621 | finish_wait(&work->waiters, &wait); |
596 | return 0; | 622 | |
623 | return ret; | ||
597 | } | 624 | } |
598 | 625 | ||
599 | /** | 626 | /** |