Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psock_udp_sendto should call udp_wrbuffer_tryalloc for nonblock socket #20

Merged
merged 1 commit into from
Dec 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions net/udp/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,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 @@ -700,18 +700,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 @@ -169,6 +169,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