• Steven Rostedt's avatar
    ring-buffer: use commit counters for commit pointer accounting · fa743953
    Steven Rostedt authored
    The ring buffer is made up of three sets of pointers.
    
    The head page pointer, which points to the next page for the reader to
    get.
    
    The commit pointer and commit index, which points to the page and index
    of the last committed write respectively.
    
    The tail pointer and tail index, which points to the page and the index
    of the last reserved data respectively (non committed).
    
    The commit pointer is only moved forward by the outer most writer.
    If a nested writer comes in, it will not move the pointer forward.
    
    The current implementation has a flaw. It assumes that the outer most
    writer successfully reserved data. There's a small race window where
    the outer most writer could find the tail pointer, but a nested
    writer could come in (via interrupt) and move the tail forward, and
    even the commit forward.
    
    The outer writer would not realized the commit moved forward and the
    accounting will break.
    
    This patch changes the design to use counters in the per cpu buffers
    to keep track of commits. The counters are incremented at the start
    of the commit, and decremented at the end. If the end commit counter
    is 1, then it moves the commit pointers. A loop is made to check for
    races between checking and moving the commit pointers. Only the outer
    commit should move the pointers anyway.
    
    The test of knowing if a reserve is equal to the last commit update
    is still needed to know for time keeping. The time code is much less
    racey than the commit updates.
    
    This change not only solves the mentioned race, but also makes the
    code simpler.
    
    [ Impact: fix commit race and simplify code ]
    Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    fa743953
ring_buffer.c 78.1 KB