Ok, let’s assume I have created a stream buff with requested length of 0x40 which internally got increased to 0x41. Then let’s assume xNextHead is at 0x40 resulting fro a couple of 8 byte writes.
Now, I am trying to write another 8 bytes. Eventually is reaches the code below.
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
will evaluate to 1 from min(0x41-0x40, 8)
This leads to a memcpy of 1 byte.
Since we have a left over of 7 bytes, the second memcpy will access &pucData[1] unaligned to write into &( pxStreamBuffer->pucBuffer[ 0 ] ) which is aligned but doesn’t help much since the source isn’t.
As a result xNextHead will be 7.
This leads to the situation that in the next call of prvWriteBytesToBuffer we will read 8 bytes aligned from pucData but will write unaligned to &( pxStreamBuffer->pucBuffer[ 7 ] )
I verified this scenario with a debugger. It came across to me when using actually a buggy memcpy implementation (which isn’t the fault freertos of course).
But while doing this, this odd wrap around really destroys all memcpy SIMD and similar optimizations.
Further, I still no understand why this extra byte is added? I have done circular buffers many time with exclusive read access from one context and write from another. If you like to have e.g. a 1024 bytes ring buffer to feed like 16 byte chunks in high speed, I have no idea for what use byte 1025 really is.
Anyway, thanks for replay!
Best
Rolf
======================
static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount )
{
size_t xNextHead, xFirstLength;
configASSERT( xCount > ( size_t ) 0 );
xNextHead = pxStreamBuffer->xHead;
/* Calculate the number of bytes that can be added in the first write -
which may be less than the total number of bytes that need to be added if
the buffer will wrap back to the beginning. */
xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
/* Write as many bytes as can be written in the first write. */
configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength );
( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
/* If the number of bytes written was less than the number that could be
written in the first write… */
if( xCount > xFirstLength )
{
/* …then write the remaining bytes to the start of the buffer. */
configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xNextHead += xCount;
if( xNextHead >= pxStreamBuffer->xLength )
{
xNextHead -= pxStreamBuffer->xLength;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
pxStreamBuffer->xHead = xNextHead;
return xCount;
}