TCP: add writable check during poll
When a poll requesting POLLOUT happens, the poll should return immediately if a write will not block. This change adds that, as opposed to the old behaviour of blocking until a timer from the Ethernet driver eventually triggers the poll to complete. This is only implemented for buffered TCP. Unbuffered TCP should behave as before.
This commit is contained in:
parent
99f5fcda70
commit
df211ee46a
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp.h
|
||||
*
|
||||
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2014-2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -1143,6 +1143,35 @@ struct socket;
|
||||
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
||||
size_t len);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_tcp_cansend
|
||||
*
|
||||
* Description:
|
||||
* psock_tcp_cansend() returns a value indicating if a write to the socket
|
||||
* would block. No space in the buffer is actually reserved, so it is
|
||||
* possible that the write may still block if the buffer is filled by
|
||||
* another means.
|
||||
*
|
||||
* Parameters:
|
||||
* psock An instance of the internal socket structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK
|
||||
* At least one byte of data could be succesfully written.
|
||||
* -EWOULDBLOCK
|
||||
* There is no room in the output buffer.
|
||||
* -EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* -ENOTCONN
|
||||
* The socket is not connected.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_tcp_cansend(FAR struct socket *psock);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_wrbuffer_initialize
|
||||
*
|
||||
@ -1197,6 +1226,21 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void);
|
||||
void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb);
|
||||
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_wrbuffer_test
|
||||
*
|
||||
* Description:
|
||||
* Check if there is room in the write buffer. Does not reserve any space.
|
||||
*
|
||||
* Assumptions:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
int tcp_wrbuffer_test(void);
|
||||
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_wrbuffer_dump
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_netpoll.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011-2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2011-2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -282,6 +282,10 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
|
||||
fds->revents |= (POLLERR | POLLHUP);
|
||||
}
|
||||
else if (_SS_ISCONNECTED(psock->s_flags) && psock_tcp_cansend(psock) >= 0)
|
||||
{
|
||||
fds->revents |= (POLLWRNORM & fds->events);
|
||||
}
|
||||
|
||||
/* Check if any requested events are already in effect */
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_send_buffered.c
|
||||
*
|
||||
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Jason Jiang <jasonj@live.cn>
|
||||
*
|
||||
@ -1104,4 +1104,53 @@ errout:
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_tcp_cansend
|
||||
*
|
||||
* Description:
|
||||
* psock_tcp_cansend() returns a value indicating if a write to the socket
|
||||
* would block. No space in the buffer is actually reserved, so it is
|
||||
* possible that the write may still block if the buffer is filled by
|
||||
* another means.
|
||||
*
|
||||
* Parameters:
|
||||
* psock An instance of the internal socket structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK
|
||||
* At least one byte of data could be succesfully written.
|
||||
* -EWOULDBLOCK
|
||||
* There is no room in the output buffer.
|
||||
* -EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* -ENOTCONN
|
||||
* The socket is not connected.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_tcp_cansend(FAR struct socket *psock)
|
||||
{
|
||||
if (!psock || psock->s_crefs <= 0)
|
||||
{
|
||||
ndbg("ERROR: Invalid socket\n");
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
|
||||
{
|
||||
ndbg("ERROR: Not connected\n");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (tcp_wrbuffer_test())
|
||||
{
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||
|
@ -880,4 +880,30 @@ errout:
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_tcp_cansend
|
||||
*
|
||||
* Description:
|
||||
* psock_tcp_cansend() returns a value indicating if a write to the socket
|
||||
* would block. It is still possible that the write may block if another
|
||||
* write occurs first.
|
||||
*
|
||||
* Parameters:
|
||||
* psock An instance of the internal socket structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK (Function not implemented).
|
||||
*
|
||||
* Assumptions:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_tcp_cansend(FAR struct socket *psock)
|
||||
{
|
||||
/* TODO: return OK unless someone is waiting for a packet to send */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP && !CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||
|
@ -201,4 +201,22 @@ void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb)
|
||||
sem_post(&g_wrbuffer.sem);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_wrbuffer_test
|
||||
*
|
||||
* Description:
|
||||
* Check if there is room in the write buffer. Does not reserve any space.
|
||||
*
|
||||
* Assumptions:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int tcp_wrbuffer_test(void)
|
||||
{
|
||||
int val = 0;
|
||||
sem_getvalue(&g_wrbuffer.sem, &val);
|
||||
return val > 0 ? OK : ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||
|
Loading…
Reference in New Issue
Block a user