@ -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 <string.h>
# if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.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),
# 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),
# define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
# 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),
const struct memp_desc * memp_pools [ MEMP_MAX ] = {
# define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
# 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_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
# 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 */
# endif /* MEMP_OVERFLOW_CHECK */
MEMP_STATS_DEC ( used , type ) ;
# if MEMP_OVERFLOW_CHECK == 2
memp_overflow_check_element_overflow ( memp , desc ) ;
memp_overflow_check_element_underflow ( memp , desc ) ;
# endif /* MEMP_OVERFLOW_CHECK */
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 ) ;