Skip to content
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