@shayan_mukhtar, thank you for reporting this.
First a short explanation: every socket has an RX and a TX stream, i.e. for reception and for the transmission of data. These are independent objects.
These streams are only created when needed. And like @rtel mentioned: “a socket can only have one reader and one writer”, which may be the same task.
An RX stream uses 3 pointers:
uxTail - uxHead - uxFront
A user task reads from the RX stream with
The IP-task writes to this stream in a “private” function
A TX stream also uses 3 pointers:
uxTail - uxMid - uxHead
A user task writes to the TX stream with
The IP-task reads from the TX stream in a private function
The problem that you describe has to do with the RX-stream, right?
Data has been received and is being added to the RX stream when
Theory: just before
uxFront is advanced, there is a context switch and
FreeRTOS_recv() compares uxTail with uxFront, and concludes erroneously that the RX socket has no space.
I think this was not reported before because most developers assign a different (usually higher) priority to the IP-task.
In your project the IP-task and the user task seem to have the same priority and the clock tick will lead to a task switch, correct?
- The read from the socket works, and the tail pointer is incremented
Right, that happens in
- If in that same task a write is attempted to the socket, in the window update logic, the front pointer is now behind the tail pointer
I don’t understand this. Writing to a socket with
FreeRTOS_send() has nothing to do with reading from a socket.
uxFront only plays a role in the RX stream.
The only thing where the user task reads uxFront is here in
uxStreamBufferFrontSpace(), which is called here:
/* We had reached the low-water mark, now see if the flag
* can be cleared */
size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
pxSocket->u.xTCP.bits.bLowWater = pdFALSE;
pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
The “the window update logic” is performed by the IP-task. Seen from the IP-task, the value of
uxFront is up-to-date.
- This causes the stack to erroneously state the TCP receive window is 0
In case the tasks have equal priority and when preemption / time-slicing is enabled.
How easy is it for you to replicate the problem?
If it occurs easily you could try to suspend the scheduler while updating
if( uxOffset == 0U )
/* ( uxOffset == 0 ) means: write at uxHead position */
uxNextHead += uxCount;
if( uxNextHead >= pxBuffer->LENGTH )
uxNextHead -= pxBuffer->LENGTH;
pxBuffer->uxHead = uxNextHead;
if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )
/* Advance the front pointer */
pxBuffer->uxFront = uxNextHead;