net/tcp: add support for send timeout on buffer mode
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
848d1ef0b7
commit
f073ed3a44
@ -984,6 +984,34 @@ static uint32_t tcp_max_wrb_size(FAR struct tcp_conn_s *conn)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: tcp_send_gettimeout
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Calculate the send timeout
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static unsigned int tcp_send_gettimeout(clock_t start, unsigned int timeout)
|
||||||
|
{
|
||||||
|
unsigned int elapse;
|
||||||
|
|
||||||
|
if (timeout != UINT_MAX)
|
||||||
|
{
|
||||||
|
elapse = TICK2MSEC(clock_systime_ticks() - start);
|
||||||
|
if (elapse >= timeout)
|
||||||
|
{
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout -= elapse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1050,9 +1078,11 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
FAR struct tcp_conn_s *conn;
|
FAR struct tcp_conn_s *conn;
|
||||||
FAR struct tcp_wrbuffer_s *wrb;
|
FAR struct tcp_wrbuffer_s *wrb;
|
||||||
FAR const uint8_t *cp;
|
FAR const uint8_t *cp;
|
||||||
|
unsigned int timeout;
|
||||||
ssize_t result = 0;
|
ssize_t result = 0;
|
||||||
bool nonblock;
|
bool nonblock;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
clock_t start;
|
||||||
|
|
||||||
if (psock == NULL || psock->s_type != SOCK_STREAM ||
|
if (psock == NULL || psock->s_type != SOCK_STREAM ||
|
||||||
psock->s_conn == NULL)
|
psock->s_conn == NULL)
|
||||||
@ -1108,6 +1138,8 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
|
|
||||||
nonblock = _SS_ISNONBLOCK(conn->sconn.s_flags) ||
|
nonblock = _SS_ISNONBLOCK(conn->sconn.s_flags) ||
|
||||||
(flags & MSG_DONTWAIT) != 0;
|
(flags & MSG_DONTWAIT) != 0;
|
||||||
|
start = clock_systime_ticks();
|
||||||
|
timeout = _SO_TIMEOUT(conn->sconn.s_sndtimeo);
|
||||||
|
|
||||||
/* Dump the incoming buffer */
|
/* Dump the incoming buffer */
|
||||||
|
|
||||||
@ -1172,7 +1204,12 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
goto errout_with_lock;
|
goto errout_with_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_lockedwait_uninterruptible(&conn->snd_sem);
|
ret = net_timedwait_uninterruptible(&conn->snd_sem,
|
||||||
|
tcp_send_gettimeout(start, timeout));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_SEND_BUFSIZE */
|
#endif /* CONFIG_NET_SEND_BUFSIZE */
|
||||||
|
|
||||||
@ -1210,13 +1247,12 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
{
|
{
|
||||||
wrb = tcp_wrbuffer_tryalloc();
|
wrb = tcp_wrbuffer_tryalloc();
|
||||||
ninfo("new wrb %p (non blocking)\n", wrb);
|
ninfo("new wrb %p (non blocking)\n", wrb);
|
||||||
DEBUGASSERT(wrb == NULL || TCP_WBPKTLEN(wrb) == 0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wrb = tcp_wrbuffer_alloc();
|
wrb = tcp_wrbuffer_timedalloc(tcp_send_gettimeout(start,
|
||||||
|
timeout));
|
||||||
ninfo("new wrb %p\n", wrb);
|
ninfo("new wrb %p\n", wrb);
|
||||||
DEBUGASSERT(TCP_WBPKTLEN(wrb) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrb == NULL)
|
if (wrb == NULL)
|
||||||
@ -1224,7 +1260,20 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
/* A buffer allocation error occurred */
|
/* A buffer allocation error occurred */
|
||||||
|
|
||||||
nerr("ERROR: Failed to allocate write buffer\n");
|
nerr("ERROR: Failed to allocate write buffer\n");
|
||||||
ret = nonblock ? -EAGAIN : -ENOMEM;
|
|
||||||
|
if (nonblock)
|
||||||
|
{
|
||||||
|
ret = -EAGAIN;
|
||||||
|
}
|
||||||
|
else if (timeout != UINT_MAX)
|
||||||
|
{
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
goto errout_with_lock;
|
goto errout_with_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1311,8 +1360,12 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
* we risk a deadlock with other threads competing on IOBs.
|
* we risk a deadlock with other threads competing on IOBs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
iob = net_ioballoc(true, IOBUSER_NET_TCP_WRITEBUFFER);
|
iob = net_iobtimedalloc(true, tcp_send_gettimeout(start, timeout),
|
||||||
iob_free_chain(iob, IOBUSER_NET_TCP_WRITEBUFFER);
|
IOBUSER_NET_TCP_WRITEBUFFER);
|
||||||
|
if (iob != NULL)
|
||||||
|
{
|
||||||
|
iob_free_chain(iob, IOBUSER_NET_TCP_WRITEBUFFER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump I/O buffer chain */
|
/* Dump I/O buffer chain */
|
||||||
|
Loading…
Reference in New Issue
Block a user