From c838e1ed5b8c42648de227773b9d9aa27370fc04 Mon Sep 17 00:00:00 2001 From: Dirk Ziegelmeier Date: Thu, 12 Nov 2015 08:45:04 +0100 Subject: [PATCH] Implement possibility to declare private memory pools. This is useful to decouple some apps from the core (SNMP stack) or make contrib app useage simpler (httpserver_raw) . --- src/core/mem.c | 13 +- src/core/memp.c | 388 ++++++++++++------------------ src/include/lwip/memp.h | 78 +++--- src/include/lwip/opt.h | 9 - src/include/lwip/priv/memp_priv.h | 161 +++++++++++++ src/include/lwip/stats.h | 2 + 6 files changed, 370 insertions(+), 281 deletions(-) create mode 100644 src/include/lwip/priv/memp_priv.h diff --git a/src/core/mem.c b/src/core/mem.c index b2ddd98e..ffc0c292 100644 --- a/src/core/mem.c +++ b/src/core/mem.c @@ -66,6 +66,11 @@ #include #if MEM_USE_POOLS + +#if MEMP_MEM_MALLOC +#error MEM_USE_POOLS and MEMP_MEM_MALLOC cannot be used together +#endif + /* lwIP head implemented with different sized pools */ /** @@ -89,7 +94,7 @@ again: #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ /* is this pool big enough to hold an element of the required size plus a struct memp_malloc_helper that saves the pool this element came from? */ - if (required_size <= memp_sizes[poolnr]) { + if (required_size <= memp_pools[poolnr]->size) { break; } } @@ -119,7 +124,7 @@ again: #if MEMP_OVERFLOW_CHECK /* initialize unused memory */ element->size = size; - memset((u8_t*)ret + size, 0xcd, memp_sizes[poolnr] - size); + memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); #endif /* MEMP_OVERFLOW_CHECK */ return ret; } @@ -150,9 +155,9 @@ mem_free(void *rmem) { u16_t i; LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", - hmem->size <= memp_sizes[hmem->poolnr]); + hmem->size <= memp_pools[hmem->poolnr]->size); /* check that unused memory remained untouched */ - for (i = hmem->size; i < memp_sizes[hmem->poolnr]; i++) { + for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { u8_t data = *((u8_t*)rmem + i); LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); } diff --git a/src/core/memp.c b/src/core/memp.c index 8ebde2d8..eff18f48 100644 --- a/src/core/memp.c +++ b/src/core/memp.c @@ -64,155 +64,47 @@ #include "lwip/nd6.h" #include "lwip/ip6_frag.h" #include "lwip/mld6.h" +#include "lwip/tcp.h" +#include "lwip/tcpip.h" #include "lwip/priv/tcp_priv.h" #include "lwip/priv/tcpip_priv.h" #include -#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) +#include "lwip/priv/memp_std.h" -struct memp { - struct memp *next; -#if MEMP_OVERFLOW_CHECK - const char *file; - int line; -#endif /* MEMP_OVERFLOW_CHECK */ -}; - -#if MEMP_OVERFLOW_CHECK -/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning - * and at the end of each element, initialize them as 0xcd and check - * them later. */ -/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, - * every single element in each pool is checked! - * This is VERY SLOW but also very helpful. */ -/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in - * lwipopts.h to change the amount reserved for checking. */ -#ifndef MEMP_SANITY_REGION_BEFORE -#define MEMP_SANITY_REGION_BEFORE 16 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#if MEMP_SANITY_REGION_BEFORE > 0 -#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) -#else -#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#ifndef MEMP_SANITY_REGION_AFTER -#define MEMP_SANITY_REGION_AFTER 16 -#endif /* MEMP_SANITY_REGION_AFTER*/ -#if MEMP_SANITY_REGION_AFTER > 0 -#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) -#else -#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_AFTER*/ - -/* MEMP_SIZE: save space for struct memp and for sanity check */ -#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) - -#else /* MEMP_OVERFLOW_CHECK */ - -/* No sanity checks - * We don't need to preserve the struct memp while not allocated, so we - * can save a little space and set MEMP_SIZE to 0. - */ -#define MEMP_SIZE 0 -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_OVERFLOW_CHECK */ - -/** This array holds the first free element of each pool. - * Elements form a linked list. */ -static struct memp *memp_tab[MEMP_MAX]; - -#else /* MEMP_MEM_MALLOC */ - -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_MEM_MALLOC */ - -/** This array holds the element sizes of each pool. */ -#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC && !MEMP_USE_CUSTOM_POOLS -static -#endif -const u16_t memp_sizes[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +const struct memp_desc *memp_pools[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, #include "lwip/priv/memp_std.h" }; #if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ -/** This array holds the number of elements in each pool. */ -static const u16_t memp_num[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) (num), -#include "lwip/priv/memp_std.h" -}; - -/** This array holds a textual description of each pool. */ -#ifdef LWIP_DEBUG -static const char *memp_desc[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) (desc), -#include "lwip/priv/memp_std.h" -}; -#endif /* LWIP_DEBUG */ - -#if MEMP_SEPARATE_POOLS - -/** This creates each memory pool. These are named memp_memory_XXX_base (where - * XXX is the name of the pool defined in memp_std.h). - * To relocate a pool, declare it as extern in cc.h. Example for GCC: - * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; - */ -#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ - [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; -#include "lwip/priv/memp_std.h" - -/** This array holds the base of each memory pool. */ -static u8_t *const memp_bases[] = { -#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, -#include "lwip/priv/memp_std.h" -}; - -#else /* MEMP_SEPARATE_POOLS */ - -/** This is the actual memory used by the pools (all pools in one big block). */ -static u8_t memp_memory[MEM_ALIGNMENT - 1 -#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) -#include "lwip/priv/memp_std.h" -]; - -#endif /* MEMP_SEPARATE_POOLS */ - #if MEMP_SANITY_CHECK /** * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". */ static int -memp_sanity(void) +memp_sanity(const struct memp_desc *desc) { - s16_t i; struct memp *t, *h; - for (i = 0; i < MEMP_MAX; i++) { - t = memp_tab[i]; - if (t != NULL) { - for (h = t->next; (t != NULL) && (h != NULL); t = t->next, - h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { - if (t == h) { - return 0; - } + t = *desc->tab; + if (t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { + if (t == h) { + return 0; } } } + return 1; } #endif /* MEMP_SANITY_CHECK*/ + #if MEMP_OVERFLOW_CHECK -#if defined(LWIP_DEBUG) && MEMP_STATS -static const char * memp_overflow_names[] = { -#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, -#include "lwip/priv/memp_std.h" - }; -#endif /** * Check if a memp element was victim of an overflow @@ -222,25 +114,16 @@ static const char * memp_overflow_names[] = { * @param memp_type the pool p comes from */ static void -memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) +memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) { u16_t k; u8_t *m; #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; + m = (u8_t*)p + MEMP_SIZE + desc->size; for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { if (m[k] != 0xcd) { char errstr[128] = "detected memp overflow in pool "; - char digit[] = "0"; - if (memp_type >= 10) { - digit[0] = '0' + (memp_type/10); - strcat(errstr, digit); - } - digit[0] = '0' + (memp_type%10); - strcat(errstr, digit); -#if defined(LWIP_DEBUG) && MEMP_STATS - strcat(errstr, memp_overflow_names[memp_type]); -#endif + strcat(errstr, desc->desc); LWIP_ASSERT(errstr, 0); } } @@ -255,7 +138,7 @@ memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) * @param memp_type the pool p comes from */ static void -memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) +memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) { u16_t k; u8_t *m; @@ -264,16 +147,7 @@ memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { if (m[k] != 0xcd) { char errstr[128] = "detected memp underflow in pool "; - char digit[] = "0"; - if (memp_type >= 10) { - digit[0] = '0' + (memp_type/10); - strcat(errstr, digit); - } - digit[0] = '0' + (memp_type%10); - strcat(errstr, digit); -#if defined(LWIP_DEBUG) && MEMP_STATS - strcat(errstr, memp_overflow_names[memp_type]); -#endif + strcat(errstr, desc->desc); LWIP_ASSERT(errstr, 0); } } @@ -291,28 +165,19 @@ memp_overflow_check_all(void) u16_t i, j; struct memp *p; -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { - memp_overflow_check_element_overflow(p, i); - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + p = (struct memp *)(size_t)(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_overflow(p, memp_pools[i]); + p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED); } } -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { - memp_overflow_check_element_underflow(p, i); - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + p = (struct memp *)(size_t)(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_underflow(p, memp_pools[i]); + p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED); } } } @@ -321,34 +186,52 @@ memp_overflow_check_all(void) * Initialize the restricted areas of all memp elements in every pool. */ static void -memp_overflow_init(void) +memp_overflow_init(const struct memp_desc *desc) { - u16_t i, j; + u16_t i; struct memp *p; u8_t *m; -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ - for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { + p = (struct memp *)(size_t)(desc->base); + for (i = 0; i < desc->num; ++i) { #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); #endif #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; - memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); + m = (u8_t*)p + MEMP_SIZE + desc->size; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); #endif - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); - } + p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + desc->size + MEMP_SANITY_REGION_AFTER_ALIGNED); } } #endif /* MEMP_OVERFLOW_CHECK */ + +void +memp_init_pool(const struct memp_desc *desc) +{ + int i; + struct memp *memp; + + *desc->tab = NULL; + memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); + /* create a linked list of memp elements */ + for (i = 0; i < desc->num; ++i) { + memp->next = *desc->tab; + *desc->tab = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(desc); +#endif /* MEMP_OVERFLOW_CHECK */ +} + /** * Initialize this module. * @@ -357,43 +240,62 @@ memp_overflow_init(void) void memp_init(void) { - struct memp *memp; - u16_t i, j; + u16_t i; for (i = 0; i < MEMP_MAX; ++i) { MEMP_STATS_AVAIL(used, i, 0); MEMP_STATS_AVAIL(max, i, 0); MEMP_STATS_AVAIL(err, i, 0); - MEMP_STATS_AVAIL(avail, i, memp_num[i]); + MEMP_STATS_AVAIL(avail, i, memp_pools[i]->num); } -#if !MEMP_SEPARATE_POOLS - memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ /* for every pool: */ for (i = 0; i < MEMP_MAX; ++i) { - memp_tab[i] = NULL; -#if MEMP_SEPARATE_POOLS - memp = (struct memp*)LWIP_MEM_ALIGN(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - /* create a linked list of memp elements */ - for (j = 0; j < memp_num[i]; ++j) { - memp->next = memp_tab[i]; - memp_tab[i] = memp; - memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] -#if MEMP_OVERFLOW_CHECK - + MEMP_SANITY_REGION_AFTER_ALIGNED -#endif - ); - } + memp_init_pool(memp_pools[i]); } + #if MEMP_OVERFLOW_CHECK - memp_overflow_init(); /* check everything a first time to see if it worked */ memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK */ } +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc_pool(const struct memp_desc *desc) +#else +memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + + memp = *desc->tab; + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + if (memp != NULL) { + *desc->tab = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + /** * Get an element from a specific pool. * @@ -412,31 +314,30 @@ memp_malloc(memp_t type) memp_malloc_fn(memp_t type, const char* file, const int line) #endif { - struct memp *memp; + void *memp; SYS_ARCH_DECL_PROTECT(old_level); LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); SYS_ARCH_PROTECT(old_level); + #if MEMP_OVERFLOW_CHECK >= 2 memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */ - memp = memp_tab[type]; +#if !MEMP_OVERFLOW_CHECK + memp = memp_malloc_pool(memp_pools[type]); +#else + memp = memp_malloc_pool_fn(memp_pools[type], file, line); +#endif if (memp != NULL) { - memp_tab[type] = memp->next; -#if MEMP_OVERFLOW_CHECK - memp->next = NULL; - memp->file = file; - memp->line = line; -#endif /* MEMP_OVERFLOW_CHECK */ - MEMP_STATS_INC_USED(used, type); - LWIP_ASSERT("memp_malloc: memp properly aligned", - ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); - memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + MEMP_STATS_INC(used, type); + if(MEMP_STATS_GET(used, type) > MEMP_STATS_GET(max, type)) { + MEMP_STATS_AVAIL(max, type, MEMP_STATS_GET(used, type)); + } } else { - LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_pools[type]->desc)); MEMP_STATS_INC(err, type); } @@ -445,14 +346,8 @@ memp_malloc_fn(memp_t type, const char* file, const int line) return memp; } -/** - * Put an element back into its pool. - * - * @param type the pool where to put mem - * @param mem the memp element to free - */ void -memp_free(memp_t type, void *mem) +memp_free_pool(const struct memp_desc* desc, void *mem) { struct memp *memp; #ifdef LWIP_HOOK_MEMP_AVAILABLE @@ -469,28 +364,53 @@ memp_free(memp_t type, void *mem) memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); SYS_ARCH_PROTECT(old_level); -#if MEMP_OVERFLOW_CHECK -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#else - memp_overflow_check_element_overflow(memp, type); - memp_overflow_check_element_underflow(memp, type); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#if MEMP_OVERFLOW_CHECK == 2 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); #endif /* MEMP_OVERFLOW_CHECK */ - MEMP_STATS_DEC(used, type); - - memp->next = memp_tab[type]; + memp->next = *desc->tab; #ifdef LWIP_HOOK_MEMP_AVAILABLE - old_first = memp_tab[type]; + old_first = *desc->tab; #endif - memp_tab[type] = memp; + *desc->tab = memp; #if MEMP_SANITY_CHECK - LWIP_ASSERT("memp sanity", memp_sanity()); + LWIP_ASSERT("memp sanity", memp_sanity(desc)); #endif /* MEMP_SANITY_CHECK */ SYS_ARCH_UNPROTECT(old_level); +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ +#ifdef LWIP_HOOK_MEMP_AVAILABLE + struct memp *old_first; +#endif + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + MEMP_STATS_DEC(used, type); + + memp_free_pool(memp_pools[type], mem); + + SYS_ARCH_UNPROTECT(old_level); + #ifdef LWIP_HOOK_MEMP_AVAILABLE if (old_first == NULL) { LWIP_HOOK_MEMP_AVAILABLE(type); diff --git a/src/include/lwip/memp.h b/src/include/lwip/memp.h index 9e3808e8..e8c2646c 100644 --- a/src/include/lwip/memp.h +++ b/src/include/lwip/memp.h @@ -33,8 +33,6 @@ #ifndef LWIP_HDR_MEMP_H #define LWIP_HDR_MEMP_H -#include "lwip/opt.h" - #ifdef __cplusplus extern "C" { #endif @@ -50,49 +48,60 @@ typedef enum { MEMP_MAX } memp_t; -#if MEM_USE_POOLS -/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ -typedef enum { - /* Get the first (via: - MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ - MEMP_POOL_HELPER_FIRST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START 1 -#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 -#define LWIP_MALLOC_MEMPOOL_END -#include "lwip/priv/memp_std.h" - ) , - /* Get the last (via: - MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ - MEMP_POOL_HELPER_LAST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START -#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * -#define LWIP_MALLOC_MEMPOOL_END 1 -#include "lwip/priv/memp_std.h" - ) -} memp_pool_helper_t; +#include "lwip/priv/memp_priv.h" -/* The actual start and stop values are here (cast them over) - We use this helper type and these defines so we can avoid using const memp_t values */ -#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) -#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) -#endif /* MEM_USE_POOLS */ +/* Private mempools example: + * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); + * .c: + * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") + * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); + * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); + * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); + * + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; + */ -#if MEMP_MEM_MALLOC || MEM_USE_POOLS || MEMP_USE_CUSTOM_POOLS -extern const u16_t memp_sizes[MEMP_MAX]; -#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS || MEMP_USE_CUSTOM_POOLS */ +extern const struct memp_desc *memp_pools[MEMP_MAX]; + +#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc *memp_ ## name #if MEMP_MEM_MALLOC -#include "mem.h" +#include "lwip/mem.h" #define memp_init() -#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_malloc(type) mem_malloc(memp_pools[type]->size) #define memp_free(type, mem) mem_free(mem) +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + const struct memp_desc memp_ ## name = { \ + LWIP_MEM_ALIGN_SIZE(size) \ + }; + +#define LWIP_MEMPOOL_INIT(name) +#define LWIP_MEMPOOL_ALLOC(name) mem_malloc(memp_ ## name.size) +#define LWIP_MEMPOOL_FREE(name, x) mem_free(x) + #else /* MEMP_MEM_MALLOC */ +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \ + \ + static struct memp *memp_tab_ ## name; \ + \ + const struct memp_desc memp_ ## name = { \ + LWIP_MEM_ALIGN_SIZE(size), \ + (num), \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + memp_memory_ ## name ## _base, \ + &memp_tab_ ## name \ + }; + +#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) +#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) +#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) + #if MEM_USE_POOLS /** This structure is used to save the pool one element came from. */ struct memp_malloc_helper @@ -102,6 +111,7 @@ struct memp_malloc_helper u16_t size; #endif /* MEMP_OVERFLOW_CHECK */ }; + #endif /* MEM_USE_POOLS */ void memp_init(void); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 0e847125..0a6d6148 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -142,15 +142,6 @@ #define MEM_SIZE 1600 #endif -/** - * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. - * This can be used to individually change the location of each pool. - * Default is one big array for all pools - */ -#ifndef MEMP_SEPARATE_POOLS -#define MEMP_SEPARATE_POOLS 0 -#endif - /** * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable * amount of bytes before and after each memp element in every pool and fills diff --git a/src/include/lwip/priv/memp_priv.h b/src/include/lwip/priv/memp_priv.h new file mode 100644 index 00000000..dea92370 --- /dev/null +++ b/src/include/lwip/priv/memp_priv.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_PRIV_H +#define LWIP_HDR_MEMP_PRIV_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/priv/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/priv/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +struct memp_desc { + /** Element size */ + u16_t size; + +#if !MEMP_MEM_MALLOC + /** Number of elements */ + u16_t num; + +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK + /** Textual description */ + const char *desc; +#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK */ + + /** Base */ + u8_t *base; + + /** First free element of each pool. Elements form a linked list. */ + struct memp **tab; +#endif /* MEMP_MEM_MALLOC */ +}; + +#ifdef LWIP_DEBUG +#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), +#else +#define DECLARE_LWIP_MEMPOOL_DESC(desc) +#endif + +void memp_init_pool(const struct memp_desc *desc); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); +#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) +#else +void *memp_malloc_pool(const struct memp_desc *desc); +#endif +void memp_free_pool(const struct memp_desc* desc, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/src/include/lwip/stats.h b/src/include/lwip/stats.h index 28750698..1952a039 100644 --- a/src/include/lwip/stats.h +++ b/src/include/lwip/stats.h @@ -339,12 +339,14 @@ void stats_init(void); #define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) #define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) #define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#define MEMP_STATS_GET(x, i) STATS_GET(memp[i].x) #else #define MEMP_STATS_AVAIL(x, i, y) #define MEMP_STATS_INC(x, i) #define MEMP_STATS_DEC(x, i) #define MEMP_STATS_INC_USED(x, i) #define MEMP_STATS_DISPLAY(i) +#define MEMP_STATS_GET(x, i) 0 #endif #if SYS_STATS