From df4cfdd4f80f484e335e363c2a9232d023197e34 Mon Sep 17 00:00:00 2001 From: Jason Carroll Date: Mon, 28 Nov 2022 12:55:12 -0800 Subject: [PATCH] Fix Windows thread calling vTaskSuspendAll / xTaskResumeAll. --- .../WinPCap/NetworkInterface.c | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c index 737a5ce835..6e543a3bde 100644 --- a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c +++ b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c @@ -103,6 +103,20 @@ static void prvInterruptSimulatorTask( void * pvParameters ); */ static void prvCreateThreadSafeBuffers( void ); +/* + * This function is equivalent to uxStreamBufferAdd from + * FreeRTOS_Stream_Buffer.c in the case that the stream buffer is being used + * as a normal circular buffer (i.e. only the tail and head pointers are + * needed). Thus, this function does not take the offset argument, and does not + * update the front pointer of the stream buffer. This allows the removal of + * the calls to vTaskSuspendAll and xTaskResumeAll, as the head and front + * pointer no longer need to be atomically updated, allowing this function to be + * safely used by a Windows thread. + */ +static size_t prvStreamBufferAdd( StreamBuffer_t * pxBuffer, + const uint8_t * pucData, + size_t uxByteCount ); + /* * Utility function used to format print messages only. */ @@ -189,6 +203,59 @@ static void prvCreateThreadSafeBuffers( void ) xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1; } } + +/*-----------------------------------------------------------*/ + +static size_t prvStreamBufferAdd( StreamBuffer_t * pxBuffer, + const uint8_t * pucData, + size_t uxByteCount ) +{ + size_t uxSpace, uxNextHead, uxFirst; + size_t uxCount = uxByteCount; + + uxSpace = uxStreamBufferGetSpace( pxBuffer ); + + /* The number of bytes that can be written is the minimum of the number of + * bytes requested and the number available. */ + uxCount = FreeRTOS_min_size_t( uxSpace, uxCount ); + + if( uxCount != 0U ) + { + uxNextHead = pxBuffer->uxHead; + + if( pucData != NULL ) + { + /* 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. */ + uxFirst = FreeRTOS_min_size_t( pxBuffer->LENGTH - uxNextHead, uxCount ); + + /* Write as many bytes as can be written in the first write. */ + ( void ) memcpy( &( pxBuffer->ucArray[ uxNextHead ] ), pucData, uxFirst ); + + /* If the number of bytes written was less than the number that + * could be written in the first write... */ + if( uxCount > uxFirst ) + { + /* ...then write the remaining bytes to the start of the + * buffer. */ + ( void ) memcpy( pxBuffer->ucArray, &( pucData[ uxFirst ] ), uxCount - uxFirst ); + } + } + + uxNextHead += uxCount; + + if( uxNextHead >= pxBuffer->LENGTH ) + { + uxNextHead -= pxBuffer->LENGTH; + } + + pxBuffer->uxHead = uxNextHead; + } + + return uxCount; +} + /*-----------------------------------------------------------*/ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, @@ -459,8 +526,16 @@ void pcap_callback( u_char * user, * Otherwise, there is no action. */ iptraceDUMP_PACKET( ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen, pdTRUE ); - uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) ); - uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen ); + /* NOTE. The prvStreamBufferAdd function is used here in place of + * uxStreamBufferAdd since the uxStreamBufferAdd call will suspend + * the FreeRTOS scheduler to atomically update the head and front + * of the stream buffer. Since xRecvBuffer is being used as a regular + * circular buffer (i.e. only the head and tail are needed), this call + * only updates the head of the buffer, removing the need to suspend + * the scheduler, and allowing this function to be safely called from + * a Windows thread. */ + prvStreamBufferAdd( xRecvBuffer, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) ); + prvStreamBufferAdd( xRecvBuffer, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen ); } } /*-----------------------------------------------------------*/