• Steven Rostedt (Google)'s avatar
    ring-buffer: Make wake once of ring_buffer_wait() more robust · b70f2938
    Steven Rostedt (Google) authored
    The default behavior of ring_buffer_wait() when passed a NULL "cond"
    parameter is to exit the function the first time it is woken up. The
    current implementation uses a counter that starts at zero and when it is
    greater than one it exits the wait_event_interruptible().
    
    But this relies on the internal working of wait_event_interruptible() as
    that code basically has:
    
      if (cond)
        return;
      prepare_to_wait();
      if (!cond)
        schedule();
      finish_wait();
    
    That is, cond is called twice before it sleeps. The default cond of
    ring_buffer_wait() needs to account for that and wait for its counter to
    increment twice before exiting.
    
    Instead, use the seq/atomic_inc logic that is used by the tracing code
    that calls this function. Add an atomic_t seq to rb_irq_work and when cond
    is NULL, have the default callback take a descriptor as its data that
    holds the rbwork and the value of the seq when it started.
    
    The wakeups will now increment the rbwork->seq and the cond callback will
    simply check if that number is different, and no longer have to rely on
    the implementation of wait_event_interruptible().
    
    Link: https://lore.kernel.org/linux-trace-kernel/20240315063115.6cb5d205@gandalf.local.home
    
    Cc: Masami Hiramatsu <mhiramat@kernel.org>
    Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
    Fixes: 7af9ded0 ("ring-buffer: Use wait_event_interruptible() in ring_buffer_wait()")
    Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
    b70f2938
ring_buffer.c 172 KB