From ffaee59f3e42b402eacfc623b81a48f6b631412c Mon Sep 17 00:00:00 2001 From: Joel Cunningham Date: Fri, 27 Apr 2018 17:42:30 -0500 Subject: [PATCH] loopif: only schedule poll when first packet is enqueued This optimizes the netif_loop_output to only schedule a call to poll when the first packet is enqueued. This ensures netif_poll is ran once per burst of packets that are sent (which is typical in a TCP transfer) The old behavior scheduled a call to poll for every packet that was enqueued and this lead to exhaustion of the MEMP_TCPIP_MSG_API memory pool and tcpip_mbox (if port is using static mbox size). The extra callbacks are wasted work because netif_poll drains the entire queue when ran This issue presented itself when large TCP transfer go across the loopback netif --- src/core/netif.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/netif.c b/src/core/netif.c index 9033b46c..6554c587 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -1060,6 +1060,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p) struct netif *stats_if = netif; #endif /* LWIP_HAVE_LOOPIF */ #endif /* MIB2_STATS */ +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + u8_t schedule_poll = 0; +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ SYS_ARCH_DECL_PROTECT(lev); /* Allocate a new pbuf */ @@ -1109,6 +1112,10 @@ netif_loop_output(struct netif *netif, struct pbuf *p) } else { netif->loop_first = r; netif->loop_last = last; +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* No existing packets queued, schedule poll */ + schedule_poll = 1; +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ } SYS_ARCH_UNPROTECT(lev); @@ -1118,7 +1125,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p) #if LWIP_NETIF_LOOPBACK_MULTITHREADING /* For multithreading environment, schedule a call to netif_poll */ - tcpip_try_callback((tcpip_callback_fn)netif_poll, netif); + if (schedule_poll) { + tcpip_try_callback((tcpip_callback_fn)netif_poll, netif); + } #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ return ERR_OK;