Skip to content
Snippets Groups Projects
  1. Oct 16, 2024
    • Rasmus Villemoes's avatar
      serial: fix circular rx buffer edge case · e6986086
      Rasmus Villemoes authored and Tom Rini's avatar Tom Rini committed
      
      The current implementation of the circular rx buffer falls into a
      common trap with circular buffers: It keeps the head/tail indices
      reduced modulo the buffer size. The problem with that is that it makes
      it impossible to distinguish "buffer full" from "buffer empty",
      because in both situations one has head==tail.
      
      This can easily be demonstrated: Build sandbox with RX_BUFFER enabled,
      set the RX_BUFFER_SIZE to 32, and try pasting the string
      
        01234567890123456789012345678901
      
      Nothing seems to happen, but in reality, all characters have been read
      and put into the buffer, but then tstc ends up believing nothing is in
      the buffer anyway because upriv->rd_ptr == upriv->wr_ptr.
      
      A better approach is to let the indices be free-running, and only
      reduce them modulo the buffer size when accessing the array. Then
      "empty" is head-tail==0 and "full" is head-tail==size. This does rely
      on the buffer size being a power-of-two and the free-running
      indices simply wrapping around to 0 when incremented beyond the
      maximal positive value.
      
      Incidentally, that change from signed to unsigned int also improves
      code generation quite a bit: In C, (signed int)%(signed int) is
      defined to have the sign of the dividend (so (-35) % 32 is -3, not
      29), and hence despite the modulus being a power-of-two, x % 32 does
      not actually compile to the same as a simple x & 31 - on x86 with -Os,
      it seems that gcc ends up emitting an idiv instruction, which is quite
      expensive.
      
      Signed-off-by: default avatarRasmus Villemoes <ravi@prevas.dk>
      Reviewed-by: Simon Glass's avatarSimon Glass <sjg@chromium.org>
      e6986086
  2. Oct 03, 2024
Loading