Skip to content

Commit b85bfaf

Browse files
author
Jason Carroll
committed
Fix Windows thread calling vTaskSuspendAll / xTaskResumeAll.
1 parent 1279a3f commit b85bfaf

File tree

1 file changed

+80
-5
lines changed

1 file changed

+80
-5
lines changed

source/portable/NetworkInterface/WinPCap/NetworkInterface.c

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ static void prvInterruptSimulatorTask( void * pvParameters );
103103
*/
104104
static void prvCreateThreadSafeBuffers( void );
105105

106+
/*
107+
* This function is equivalent to uxStreamBufferAdd from
108+
* FreeRTOS_Stream_Buffer.c in the case that the stream buffer is being used
109+
* as a normal circular buffer (i.e. only the tail and head pointers are
110+
* needed). Thus, this function does not take the offset argument, and does not
111+
* update the front pointer of the stream buffer. This allows the removal of
112+
* the calls to vTaskSuspendAll and xTaskResumeAll, as the head and front
113+
* pointer no longer need to be atomically updated, allowing this function to be
114+
* safely used by a Windows thread.
115+
*/
116+
static size_t prvStreamBufferAdd( StreamBuffer_t * pxBuffer,
117+
const uint8_t * pucData,
118+
size_t uxByteCount );
119+
106120
/*
107121
* Utility function used to format print messages only.
108122
*/
@@ -189,6 +203,59 @@ static void prvCreateThreadSafeBuffers( void )
189203
xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
190204
}
191205
}
206+
207+
/*-----------------------------------------------------------*/
208+
209+
static size_t prvStreamBufferAdd( StreamBuffer_t * pxBuffer,
210+
const uint8_t * pucData,
211+
size_t uxByteCount )
212+
{
213+
size_t uxSpace, uxNextHead, uxFirst;
214+
size_t uxCount = uxByteCount;
215+
216+
uxSpace = uxStreamBufferGetSpace( pxBuffer );
217+
218+
/* The number of bytes that can be written is the minimum of the number of
219+
* bytes requested and the number available. */
220+
uxCount = FreeRTOS_min_size_t( uxSpace, uxCount );
221+
222+
if( uxCount != 0U )
223+
{
224+
uxNextHead = pxBuffer->uxHead;
225+
226+
if( pucData != NULL )
227+
{
228+
/* Calculate the number of bytes that can be added in the first
229+
* write - which may be less than the total number of bytes that need
230+
* to be added if the buffer will wrap back to the beginning. */
231+
uxFirst = FreeRTOS_min_size_t( pxBuffer->LENGTH - uxNextHead, uxCount );
232+
233+
/* Write as many bytes as can be written in the first write. */
234+
( void ) memcpy( &( pxBuffer->ucArray[ uxNextHead ] ), pucData, uxFirst );
235+
236+
/* If the number of bytes written was less than the number that
237+
* could be written in the first write... */
238+
if( uxCount > uxFirst )
239+
{
240+
/* ...then write the remaining bytes to the start of the
241+
* buffer. */
242+
( void ) memcpy( pxBuffer->ucArray, &( pucData[ uxFirst ] ), uxCount - uxFirst );
243+
}
244+
}
245+
246+
uxNextHead += uxCount;
247+
248+
if( uxNextHead >= pxBuffer->LENGTH )
249+
{
250+
uxNextHead -= pxBuffer->LENGTH;
251+
}
252+
253+
pxBuffer->uxHead = uxNextHead;
254+
}
255+
256+
return uxCount;
257+
}
258+
192259
/*-----------------------------------------------------------*/
193260

194261
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
@@ -255,7 +322,7 @@ static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
255322
{
256323
/* Print out the list of network interfaces. The first in the list
257324
* is interface '1', not interface '0'. */
258-
for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
325+
for(xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next)
259326
{
260327
/* The descriptions of the devices can be full of spaces, clean them
261328
* a little. printf() can only be used here because the network is not
@@ -350,7 +417,7 @@ static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces
350417
/* Walk the list of devices until the selected device is located. */
351418
pxInterface = pxAllNetworkInterfaces;
352419

353-
for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )
420+
for(x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++)
354421
{
355422
pxInterface = pxInterface->next;
356423
}
@@ -459,8 +526,16 @@ void pcap_callback( u_char * user,
459526
* Otherwise, there is no action. */
460527
iptraceDUMP_PACKET( ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen, pdTRUE );
461528

462-
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) );
463-
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen );
529+
/* NOTE. The prvStreamBufferAdd function is used here in place of
530+
* uxStreamBufferAdd since the uxStreamBufferAdd call will suspend
531+
* the FreeRTOS scheduler to atomically update the head and front
532+
* of the stream buffer. Since xRecvBuffer is being used as a regular
533+
* circular buffer (i.e. only the head and tail are needed), this call
534+
* only updates the head of the buffer, removing the need to suspend
535+
* the scheduler, and allowing this function to be safely called from
536+
* a Windows thread. */
537+
prvStreamBufferAdd( xRecvBuffer, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) );
538+
prvStreamBufferAdd( xRecvBuffer, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen );
464539
}
465540
}
466541
/*-----------------------------------------------------------*/
@@ -704,7 +779,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB
704779
}
705780
else
706781
{
707-
for( uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; uxIndex++ )
782+
for(uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; uxIndex++)
708783
{
709784
size_t uxOffset = uxIndex * BUFFER_SIZE_ROUNDED_UP;
710785
NetworkBufferDescriptor_t ** ppDescriptor;

0 commit comments

Comments
 (0)