net/tcp: add interface tcp_wrbuffer_timedalloc()

add new interface to support alloc wrbuffer with timeout

Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an 2022-02-17 12:58:00 +08:00 committed by Petro Karashchenko
parent a92d5f622e
commit 1911ae2192
2 changed files with 90 additions and 72 deletions

View File

@ -1548,6 +1548,30 @@ int psock_tcp_cansend(FAR struct tcp_conn_s *conn);
void tcp_wrbuffer_initialize(void);
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
struct tcp_wrbuffer_s;
/****************************************************************************
* Name: tcp_wrbuffer_timedalloc
*
* Description:
* Allocate a TCP write buffer by taking a pre-allocated buffer from
* the free list. This function is called from TCP logic when a buffer
* of TCP data is about to sent
* This function is wrapped version of tcp_wrbuffer_alloc(),
* this wait will be terminated when the specified timeout expires.
*
* Input Parameters:
* timeout - The relative time to wait until a timeout is declared.
*
* Assumptions:
* Called from user logic with the network locked.
*
****************************************************************************/
FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout);
/****************************************************************************
* Name: tcp_wrbuffer_alloc
*
@ -1564,8 +1588,6 @@ void tcp_wrbuffer_initialize(void);
*
****************************************************************************/
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
struct tcp_wrbuffer_s;
FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void);
/****************************************************************************

View File

@ -105,6 +105,70 @@ void tcp_wrbuffer_initialize(void)
nxsem_set_protocol(&g_wrbuffer.sem, SEM_PRIO_NONE);
}
/****************************************************************************
* Name: tcp_wrbuffer_timedalloc
*
* Description:
* Allocate a TCP write buffer by taking a pre-allocated buffer from
* the free list. This function is called from TCP logic when a buffer
* of TCP data is about to sent
* This function is wrapped version of tcp_wrbuffer_alloc(),
* this wait will be terminated when the specified timeout expires.
*
* Input Parameters:
* timeout - The relative time to wait until a timeout is declared.
*
* Assumptions:
* Called from user logic with the network locked.
*
****************************************************************************/
FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout)
{
FAR struct tcp_wrbuffer_s *wrb;
int ret;
/* We need to allocate two things: (1) A write buffer structure and (2)
* at least one I/O buffer to start the chain.
*
* Allocate the write buffer structure first then the IOB. In order to
* avoid deadlocks, we will need to free the IOB first, then the write
* buffer
*/
ret = net_timedwait_uninterruptible(&g_wrbuffer.sem, timeout);
if (ret != OK)
{
return NULL;
}
/* Now, we are guaranteed to have a write buffer structure reserved
* for us in the free list.
*/
wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers);
DEBUGASSERT(wrb);
memset(wrb, 0, sizeof(struct tcp_wrbuffer_s));
/* Now get the first I/O buffer for the write buffer structure */
wrb->wb_iob = net_iobtimedalloc(true, timeout,
IOBUSER_NET_TCP_WRITEBUFFER);
/* Did we get an IOB? We should always get one except under some really
* weird error conditions.
*/
if (wrb->wb_iob == NULL)
{
nerr("ERROR: Failed to allocate I/O buffer\n");
tcp_wrbuffer_release(wrb);
return NULL;
}
return wrb;
}
/****************************************************************************
* Name: tcp_wrbuffer_alloc
*
@ -123,42 +187,7 @@ void tcp_wrbuffer_initialize(void)
FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void)
{
FAR struct tcp_wrbuffer_s *wrb;
/* We need to allocate two things: (1) A write buffer structure and (2)
* at least one I/O buffer to start the chain.
*
* Allocate the write buffer structure first then the IOB. In order to
* avoid deadlocks, we will need to free the IOB first, then the write
* buffer
*/
net_lockedwait_uninterruptible(&g_wrbuffer.sem);
/* Now, we are guaranteed to have a write buffer structure reserved
* for us in the free list.
*/
wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers);
DEBUGASSERT(wrb);
memset(wrb, 0, sizeof(struct tcp_wrbuffer_s));
/* Now get the first I/O buffer for the write buffer structure */
wrb->wb_iob = net_ioballoc(true, IOBUSER_NET_TCP_WRITEBUFFER);
/* Did we get an IOB? We should always get one except under some really
* weird error conditions.
*/
if (wrb->wb_iob == NULL)
{
nerr("ERROR: Failed to allocate I/O buffer\n");
tcp_wrbuffer_release(wrb);
return NULL;
}
return wrb;
return tcp_wrbuffer_timedalloc(UINT_MAX);
}
/****************************************************************************
@ -181,40 +210,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void)
FAR struct tcp_wrbuffer_s *tcp_wrbuffer_tryalloc(void)
{
FAR struct tcp_wrbuffer_s *wrb;
/* We need to allocate two things: (1) A write buffer structure and (2)
* at least one I/O buffer to start the chain.
*
* Allocate the write buffer structure first then the IOBG. In order to
* avoid deadlocks, we will need to free the IOB first, then the write
* buffer
*/
if (nxsem_trywait(&g_wrbuffer.sem) != OK)
{
return NULL;
}
/* Now, we are guaranteed to have a write buffer structure reserved
* for us in the free list.
*/
wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers);
DEBUGASSERT(wrb);
memset(wrb, 0, sizeof(struct tcp_wrbuffer_s));
/* Now get the first I/O buffer for the write buffer structure */
wrb->wb_iob = iob_tryalloc(false, IOBUSER_NET_TCP_WRITEBUFFER);
if (!wrb->wb_iob)
{
nerr("ERROR: Failed to allocate I/O buffer\n");
tcp_wrbuffer_release(wrb);
return NULL;
}
return wrb;
return tcp_wrbuffer_timedalloc(0);
}
/****************************************************************************