You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2019/12/31 15:52:46 UTC
[incubator-nuttx] branch master updated: psock_udp_sendto should
call udp_wrbuffer_tryalloc for nonblock socket (#20)
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 5fb5a9d psock_udp_sendto should call udp_wrbuffer_tryalloc for nonblock socket (#20)
5fb5a9d is described below
commit 5fb5a9dfddabe33966de961b03d5934f8a658084
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Dec 31 09:52:40 2019 -0600
psock_udp_sendto should call udp_wrbuffer_tryalloc for nonblock socket (#20)
net/udp/udp_wrbuffer.c: Add new function udp_wrbuffer_tryalloc()
net/udp/udp_psock_sendto_buffered.c: If the socket was opened with O_NONBLOCK, then use udp_wrbuffer_tryalloc() so that the caller will not wait for a write buffer. Return EGAIN if udp_wrbuffer_tryalloc() failes.
---
net/udp/udp.h | 21 ++++++++++++++
net/udp/udp_psock_sendto_buffered.c | 15 ++++++++--
net/udp/udp_wrbuffer.c | 56 +++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/net/udp/udp.h b/net/udp/udp.h
index 2c95052..d63b1f7 100644
--- a/net/udp/udp.h
+++ b/net/udp/udp.h
@@ -461,6 +461,27 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void);
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
/****************************************************************************
+ * Name: udp_wrbuffer_tryalloc
+ *
+ * Description:
+ * Try to allocate a UDP write buffer by taking a pre-allocated buffer from
+ * the free list. This function is called from UDP logic when a buffer
+ * of UDP data is about to be sent if the socket is non-blocking. Returns
+ * immediately if allocation fails.
+ *
+ * Input parameters:
+ * None
+ *
+ * Assumptions:
+ * Called from user logic with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
+FAR struct udp_wrbuffer_s *udp_wrbuffer_tryalloc(void);
+#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
+
+/****************************************************************************
* Name: udp_wrbuffer_release
*
* Description:
diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c
index b465edb..d987886 100644
--- a/net/udp/udp_psock_sendto_buffered.c
+++ b/net/udp/udp_psock_sendto_buffered.c
@@ -697,18 +697,27 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
if (len > 0)
{
+ net_lock();
+
/* Allocate a write buffer. Careful, the network will be momentarily
* unlocked here.
*/
- net_lock();
- wrb = udp_wrbuffer_alloc();
+ if (_SS_ISNONBLOCK(psock->s_flags))
+ {
+ wrb = udp_wrbuffer_tryalloc();
+ }
+ else
+ {
+ wrb = udp_wrbuffer_alloc();
+ }
+
if (wrb == NULL)
{
/* A buffer allocation error occurred */
nerr("ERROR: Failed to allocate write buffer\n");
- ret = -ENOMEM;
+ ret = _SS_ISNONBLOCK(psock->s_flags) ? -EAGAIN : -ENOMEM;
goto errout_with_lock;
}
diff --git a/net/udp/udp_wrbuffer.c b/net/udp/udp_wrbuffer.c
index b380c59..9248c3a 100644
--- a/net/udp/udp_wrbuffer.c
+++ b/net/udp/udp_wrbuffer.c
@@ -171,6 +171,62 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void)
}
/****************************************************************************
+ * Name: udp_wrbuffer_tryalloc
+ *
+ * Description:
+ * Try to allocate a TCP write buffer by taking a pre-allocated buffer from
+ * the free list. This function is called from UDP logic when a buffer
+ * of UDP data is about to be sent on a non-blocking socket. Returns
+ * immediately if the allocation failed.
+ *
+ * Input parameters:
+ * None
+ *
+ * Assumptions:
+ * Called from user logic with the network locked. Will return if no buffer
+ * is available.
+ *
+ ****************************************************************************/
+
+FAR struct udp_wrbuffer_s *udp_wrbuffer_tryalloc(void)
+{
+ FAR struct udp_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
+ */
+
+ 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 udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers);
+ DEBUGASSERT(wrb);
+ memset(wrb, 0, sizeof(struct udp_wrbuffer_s));
+
+ /* Now get the first I/O buffer for the write buffer structure */
+
+ wrb->wb_iob = iob_tryalloc(false, IOBUSER_NET_UDP_WRITEBUFFER);
+ if (!wrb->wb_iob)
+ {
+ nerr("ERROR: Failed to allocate I/O buffer\n");
+ udp_wrbuffer_release(wrb);
+ return NULL;
+ }
+
+ return wrb;
+}
+
+/****************************************************************************
* Name: udp_wrbuffer_release
*
* Description: