Skip to content

Commit

Permalink
psock_udp_sendto should call udp_wrbuffer_tryalloc for nonblock socket (
Browse files Browse the repository at this point in the history
apache#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.
  • Loading branch information
xiaoxiang781216 committed Dec 31, 2019
1 parent df7ef81 commit 63f4778
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 3 deletions.
21 changes: 21 additions & 0 deletions net/udp/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,27 @@ struct udp_wrbuffer_s;
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
*
Expand Down
15 changes: 12 additions & 3 deletions net/udp/udp_psock_sendto_buffered.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
56 changes: 56 additions & 0 deletions net/udp/udp_wrbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,62 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void)
return wrb;
}

/****************************************************************************
* 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
*
Expand Down

0 comments on commit 63f4778

Please sign in to comment.