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
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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,
|
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
||||||
size_t len);
|
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
|
* 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);
|
void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb);
|
||||||
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS */
|
#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
|
* Function: tcp_wrbuffer_dump
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/tcp/tcp_netpoll.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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);
|
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 */
|
/* Check if any requested events are already in effect */
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/tcp/tcp_send_buffered.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
* Jason Jiang <jasonj@live.cn>
|
* Jason Jiang <jasonj@live.cn>
|
||||||
*
|
*
|
||||||
@ -1104,4 +1104,53 @@ errout:
|
|||||||
return ERROR;
|
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 */
|
#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||||
|
@ -880,4 +880,30 @@ errout:
|
|||||||
return ERROR;
|
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 */
|
#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);
|
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 */
|
#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */
|
||||||
|
Loading…
Reference in New Issue
Block a user