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.
This commit is contained in:
parent
3187dde36c
commit
5fb5a9dfdd
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user