diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 87dab15f8a..030a52b387 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -1548,6 +1548,30 @@ int psock_tcp_cansend(FAR struct tcp_conn_s *conn); void tcp_wrbuffer_initialize(void); #endif /* CONFIG_NET_TCP_WRITE_BUFFERS */ +#ifdef CONFIG_NET_TCP_WRITE_BUFFERS + +struct tcp_wrbuffer_s; + +/**************************************************************************** + * Name: tcp_wrbuffer_timedalloc + * + * Description: + * Allocate a TCP write buffer by taking a pre-allocated buffer from + * the free list. This function is called from TCP logic when a buffer + * of TCP data is about to sent + * This function is wrapped version of tcp_wrbuffer_alloc(), + * this wait will be terminated when the specified timeout expires. + * + * Input Parameters: + * timeout - The relative time to wait until a timeout is declared. + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout); + /**************************************************************************** * Name: tcp_wrbuffer_alloc * @@ -1564,8 +1588,6 @@ void tcp_wrbuffer_initialize(void); * ****************************************************************************/ -#ifdef CONFIG_NET_TCP_WRITE_BUFFERS -struct tcp_wrbuffer_s; FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void); /**************************************************************************** diff --git a/net/tcp/tcp_wrbuffer.c b/net/tcp/tcp_wrbuffer.c index a93a2bc7f1..7fb1bec5ec 100644 --- a/net/tcp/tcp_wrbuffer.c +++ b/net/tcp/tcp_wrbuffer.c @@ -105,6 +105,70 @@ void tcp_wrbuffer_initialize(void) nxsem_set_protocol(&g_wrbuffer.sem, SEM_PRIO_NONE); } +/**************************************************************************** + * Name: tcp_wrbuffer_timedalloc + * + * Description: + * Allocate a TCP write buffer by taking a pre-allocated buffer from + * the free list. This function is called from TCP logic when a buffer + * of TCP data is about to sent + * This function is wrapped version of tcp_wrbuffer_alloc(), + * this wait will be terminated when the specified timeout expires. + * + * Input Parameters: + * timeout - The relative time to wait until a timeout is declared. + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout) +{ + FAR struct tcp_wrbuffer_s *wrb; + int ret; + + /* 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 + */ + + ret = net_timedwait_uninterruptible(&g_wrbuffer.sem, timeout); + if (ret != OK) + { + return NULL; + } + + /* Now, we are guaranteed to have a write buffer structure reserved + * for us in the free list. + */ + + wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); + DEBUGASSERT(wrb); + memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); + + /* Now get the first I/O buffer for the write buffer structure */ + + wrb->wb_iob = net_iobtimedalloc(true, timeout, + IOBUSER_NET_TCP_WRITEBUFFER); + + /* Did we get an IOB? We should always get one except under some really + * weird error conditions. + */ + + if (wrb->wb_iob == NULL) + { + nerr("ERROR: Failed to allocate I/O buffer\n"); + tcp_wrbuffer_release(wrb); + return NULL; + } + + return wrb; +} + /**************************************************************************** * Name: tcp_wrbuffer_alloc * @@ -123,42 +187,7 @@ void tcp_wrbuffer_initialize(void) FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void) { - FAR struct tcp_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 - */ - - net_lockedwait_uninterruptible(&g_wrbuffer.sem); - - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); - - /* Now get the first I/O buffer for the write buffer structure */ - - wrb->wb_iob = net_ioballoc(true, IOBUSER_NET_TCP_WRITEBUFFER); - - /* Did we get an IOB? We should always get one except under some really - * weird error conditions. - */ - - if (wrb->wb_iob == NULL) - { - nerr("ERROR: Failed to allocate I/O buffer\n"); - tcp_wrbuffer_release(wrb); - return NULL; - } - - return wrb; + return tcp_wrbuffer_timedalloc(UINT_MAX); } /**************************************************************************** @@ -181,40 +210,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void) FAR struct tcp_wrbuffer_s *tcp_wrbuffer_tryalloc(void) { - FAR struct tcp_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 IOBG. 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 tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); - - /* Now get the first I/O buffer for the write buffer structure */ - - wrb->wb_iob = iob_tryalloc(false, IOBUSER_NET_TCP_WRITEBUFFER); - if (!wrb->wb_iob) - { - nerr("ERROR: Failed to allocate I/O buffer\n"); - tcp_wrbuffer_release(wrb); - return NULL; - } - - return wrb; + return tcp_wrbuffer_timedalloc(0); } /****************************************************************************