From a65108138eb4a36f16688170ee79eadbe78364ee Mon Sep 17 00:00:00 2001 From: Asish Kumar Date: Sat, 4 Apr 2026 17:03:22 +0530 Subject: [PATCH] stream_buffer: require batching buffers to exceed trigger level Batching stream buffers are documented to unblock receivers only after the buffered byte count exceeds the trigger level, but both xStreamBufferSend() paths currently notify as soon as the count reaches it. That equality case wakes the blocked receiver too early, causing xStreamBufferReceive() to return 0 bytes while the buffer still holds exactly trigger-level data. Route both task and ISR send paths through a shared trigger helper so batching buffers require a strict greater-than check while existing stream and message buffer semantics remain unchanged. Fixes #1375 Signed-off-by: Asish Kumar --- stream_buffer.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/stream_buffer.c b/stream_buffer.c index 287bd073699..a4c6d268d11 100644 --- a/stream_buffer.c +++ b/stream_buffer.c @@ -256,6 +256,15 @@ typedef struct StreamBufferDef_t */ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION; +/* + * Returns pdTRUE when the amount of buffered data should unblock a task that + * is waiting to receive data. Stream batching buffers require the buffered + * data to exceed the trigger level, whereas stream and message buffers unblock + * when the trigger level is reached. + */ +static BaseType_t prvBytesInBufferMeetTriggerLevel( const StreamBuffer_t * const pxStreamBuffer, + size_t xBytesInBuffer ) PRIVILEGED_FUNCTION; + /* * Add xCount bytes from pucData into the pxStreamBuffer's data storage area. * This function does not update the buffer's xHead pointer, so multiple writes @@ -919,7 +928,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ); /* Was a task waiting for the data? */ - if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + if( prvBytesInBufferMeetTriggerLevel( pxStreamBuffer, prvBytesInBuffer( pxStreamBuffer ) ) != pdFALSE ) { prvSEND_COMPLETED( pxStreamBuffer ); } @@ -976,7 +985,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, if( xReturn > ( size_t ) 0 ) { /* Was a task waiting for the data? */ - if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + if( prvBytesInBufferMeetTriggerLevel( pxStreamBuffer, prvBytesInBuffer( pxStreamBuffer ) ) != pdFALSE ) { /* MISRA Ref 4.7.1 [Return value shall be checked] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ @@ -1587,6 +1596,35 @@ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) } /*-----------------------------------------------------------*/ +static BaseType_t prvBytesInBufferMeetTriggerLevel( const StreamBuffer_t * const pxStreamBuffer, + size_t xBytesInBuffer ) +{ + BaseType_t xReturn = pdFALSE; + + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_BATCHING_BUFFER ) != ( uint8_t ) 0 ) + { + if( xBytesInBuffer > pxStreamBuffer->xTriggerLevelBytes ) + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xBytesInBuffer >= pxStreamBuffer->xTriggerLevelBytes ) + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, uint8_t * const pucBuffer, size_t xBufferSizeBytes,