freeing ooseq pbufs when the pbuf pool is empty implemented for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() at regular intervals from main level.

This commit is contained in:
Simon Goldschmidt 2011-07-22 21:05:10 +02:00
parent 78ac382fdf
commit cc3b4dff20
3 changed files with 61 additions and 23 deletions

View File

@ -84,18 +84,25 @@
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_IS_EMPTY() #define PBUF_POOL_IS_EMPTY()
#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */ #else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
#ifndef PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_FREE_OOSEQ 1
#endif /* PBUF_POOL_FREE_OOSEQ */
#if PBUF_POOL_FREE_OOSEQ #if !NO_SYS
#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
#include "lwip/tcpip.h" #include "lwip/tcpip.h"
#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \
if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \
SYS_ARCH_PROTECT(old_level); \
pbuf_free_ooseq_pending = 0; \
SYS_ARCH_UNPROTECT(old_level); \
} } while(0)
#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
#endif /* !NO_SYS */
volatile u8_t pbuf_free_ooseq_pending;
#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() #define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
static u8_t pbuf_free_ooseq_queued;
/** /**
* Attempt to reclaim some memory from queued out-of-sequence TCP segments * Attempt to reclaim some memory from queued out-of-sequence TCP segments
* if we run out of pool pbufs. It's better to give priority to new packets * if we run out of pool pbufs. It's better to give priority to new packets
@ -104,15 +111,14 @@ static u8_t pbuf_free_ooseq_queued;
* This must be done in the correct thread context therefore this function * This must be done in the correct thread context therefore this function
* can only be used with NO_SYS=0 and through tcpip_callback. * can only be used with NO_SYS=0 and through tcpip_callback.
*/ */
static void void
pbuf_free_ooseq(void* arg) pbuf_free_ooseq()
{ {
struct tcp_pcb* pcb; struct tcp_pcb* pcb;
SYS_ARCH_DECL_PROTECT(old_level); SYS_ARCH_DECL_PROTECT(old_level);
LWIP_UNUSED_ARG(arg);
SYS_ARCH_PROTECT(old_level); SYS_ARCH_PROTECT(old_level);
pbuf_free_ooseq_queued = 0; pbuf_free_ooseq_pending = 0;
SYS_ARCH_UNPROTECT(old_level); SYS_ARCH_UNPROTECT(old_level);
for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
@ -126,29 +132,39 @@ pbuf_free_ooseq(void* arg)
} }
} }
/**
* Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq().
*/
static void
pbuf_free_ooseq_callback(void *arg)
{
LWIP_UNUSED_ARG(arg);
pbuf_free_ooseq();
}
/** Queue a call to pbuf_free_ooseq if not already queued. */ /** Queue a call to pbuf_free_ooseq if not already queued. */
static void static void
pbuf_pool_is_empty(void) pbuf_pool_is_empty(void)
{ {
u8_t queued;
SYS_ARCH_DECL_PROTECT(old_level); SYS_ARCH_DECL_PROTECT(old_level);
#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
SYS_ARCH_PROTECT(old_level); SYS_ARCH_PROTECT(old_level);
queued = pbuf_free_ooseq_queued; pbuf_free_ooseq_pending = 1;
pbuf_free_ooseq_queued = 1; SYS_ARCH_UNPROTECT(old_level);
#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
u8_t queued;
SYS_ARCH_PROTECT(old_level);
queued = pbuf_free_ooseq_pending;
pbuf_free_ooseq_pending = 1;
SYS_ARCH_UNPROTECT(old_level); SYS_ARCH_UNPROTECT(old_level);
if(!queued) { if(!queued) {
/* queue a call to pbuf_free_ooseq if not already queued */ /* queue a call to pbuf_free_ooseq if not already queued */
if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) { PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
SYS_ARCH_PROTECT(old_level);
pbuf_free_ooseq_queued = 0;
SYS_ARCH_UNPROTECT(old_level);
}
} }
#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
} }
#endif /* PBUF_POOL_FREE_OOSEQ */ #endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
/** /**
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).

View File

@ -60,6 +60,7 @@
#include "lwip/ip6_frag.h" #include "lwip/ip6_frag.h"
#include "lwip/mld6.h" #include "lwip/mld6.h"
#include "lwip/sys.h" #include "lwip/sys.h"
#include "lwip/pbuf.h"
/** The one and only timeout list */ /** The one and only timeout list */
static struct sys_timeo *next_timeout; static struct sys_timeo *next_timeout;
@ -428,6 +429,9 @@ sys_check_timeouts(void)
diff = LWIP_U32_DIFF(now, timeouts_last_time); diff = LWIP_U32_DIFF(now, timeouts_last_time);
do do
{ {
#if PBUF_POOL_FREE_OOSEQ
PBUF_CHECK_FREE_OOSEQ();
#endif /* PBUF_POOL_FREE_OOSEQ */
had_one = 0; had_one = 0;
tmptimeout = next_timeout; tmptimeout = next_timeout;
if (tmptimeout->time <= diff) { if (tmptimeout->time <= diff) {

View File

@ -127,6 +127,24 @@ struct pbuf_custom {
}; };
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ #endif /* LWIP_SUPPORT_CUSTOM_PBUF */
#if LWIP_TCP && TCP_QUEUE_OOSEQ
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
#ifndef PBUF_POOL_FREE_OOSEQ
#define PBUF_POOL_FREE_OOSEQ 1
#endif /* PBUF_POOL_FREE_OOSEQ */
#if NO_SYS && PBUF_POOL_FREE_OOSEQ
extern volatile u8_t pbuf_free_ooseq_pending;
void pbuf_free_ooseq();
/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
at regular intervals from main level to check if ooseq pbufs need to be
freed! */
#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \
/* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \
ooseq queued pbufs now */ \
pbuf_free_ooseq(); }}while(0)
#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */
/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ /* Initializes the pbuf module. This call is empty for now, but may not be in future. */
#define pbuf_init() #define pbuf_init()