ReactOS 0.4.16-dev-297-gc569aee
mem.c File Reference
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/err.h"
#include <string.h>
Include dependency graph for mem.c:

Go to the source code of this file.

Classes

struct  mem
 

Macros

#define LWIP_MEM_ILLEGAL_FREE(msg)   LWIP_ASSERT(msg, 0)
 
#define MEM_STATS_INC_LOCKED(x)   SYS_ARCH_LOCKED(MEM_STATS_INC(x))
 
#define MEM_STATS_INC_USED_LOCKED(x, y)   SYS_ARCH_LOCKED(MEM_STATS_INC_USED(x, y))
 
#define MEM_STATS_DEC_USED_LOCKED(x, y)   SYS_ARCH_LOCKED(MEM_STATS_DEC_USED(x, y))
 
#define MEM_SANITY_OFFSET   0
 
#define MEM_SANITY_OVERHEAD   0
 
#define MIN_SIZE   12
 
#define MIN_SIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
 
#define SIZEOF_STRUCT_MEM   LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
 
#define MEM_SIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
 
#define LWIP_RAM_HEAP_POINTER   ram_heap
 
#define LWIP_MEM_FREE_DECL_PROTECT()
 
#define LWIP_MEM_FREE_PROTECT()   sys_mutex_lock(&mem_mutex)
 
#define LWIP_MEM_FREE_UNPROTECT()   sys_mutex_unlock(&mem_mutex)
 
#define LWIP_MEM_ALLOC_DECL_PROTECT()
 
#define LWIP_MEM_ALLOC_PROTECT()
 
#define LWIP_MEM_ALLOC_UNPROTECT()
 
#define LWIP_MEM_LFREE_VOLATILE
 
#define MEM_SANITY()
 
#define mem_overflow_init_element(mem, size)
 
#define mem_overflow_check_element(mem)
 

Functions

 LWIP_DECLARE_MEMORY_ALIGNED (ram_heap, MEM_SIZE_ALIGNED+(2U *SIZEOF_STRUCT_MEM))
 
static struct memptr_to_mem (mem_size_t ptr)
 
static mem_size_t mem_to_ptr (void *mem)
 
static void plug_holes (struct mem *mem)
 
void mem_init (void)
 
static int mem_link_valid (struct mem *mem)
 
void mem_free (void *rmem)
 
voidmem_trim (void *rmem, mem_size_t new_size)
 
voidmem_malloc (mem_size_t size_in)
 
voidmem_calloc (mem_size_t count, mem_size_t size)
 

Variables

static u8_tram
 
static struct memram_end
 
static sys_mutex_t mem_mutex
 
static struct mem *LWIP_MEM_LFREE_VOLATILE lfree
 

Detailed Description

Dynamic memory manager

This is a lightweight replacement for the standard C library malloc().

If you want to use the standard C library malloc() instead, define MEM_LIBC_MALLOC to 1 in your lwipopts.h

To let mem_malloc() use pools (prevents fragmentation and is much faster than a heap but might waste some memory), define MEM_USE_POOLS to 1, define MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list of pools like this (more pools can be added between _START and _END):

Define three pools with sizes 256, 512, and 1512 bytes LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END

Definition in file mem.c.

Macro Definition Documentation

◆ LWIP_MEM_ALLOC_DECL_PROTECT

#define LWIP_MEM_ALLOC_DECL_PROTECT ( )

Definition at line 413 of file mem.c.

◆ LWIP_MEM_ALLOC_PROTECT

#define LWIP_MEM_ALLOC_PROTECT ( )

Definition at line 414 of file mem.c.

◆ LWIP_MEM_ALLOC_UNPROTECT

#define LWIP_MEM_ALLOC_UNPROTECT ( )

Definition at line 415 of file mem.c.

◆ LWIP_MEM_FREE_DECL_PROTECT

#define LWIP_MEM_FREE_DECL_PROTECT ( )

Definition at line 409 of file mem.c.

◆ LWIP_MEM_FREE_PROTECT

#define LWIP_MEM_FREE_PROTECT ( )    sys_mutex_lock(&mem_mutex)

Definition at line 410 of file mem.c.

◆ LWIP_MEM_FREE_UNPROTECT

#define LWIP_MEM_FREE_UNPROTECT ( )    sys_mutex_unlock(&mem_mutex)

Definition at line 411 of file mem.c.

◆ LWIP_MEM_ILLEGAL_FREE

#define LWIP_MEM_ILLEGAL_FREE (   msg)    LWIP_ASSERT(msg, 0)

Definition at line 71 of file mem.c.

◆ LWIP_MEM_LFREE_VOLATILE

#define LWIP_MEM_LFREE_VOLATILE

Definition at line 416 of file mem.c.

◆ LWIP_RAM_HEAP_POINTER

#define LWIP_RAM_HEAP_POINTER   ram_heap

Definition at line 380 of file mem.c.

◆ mem_overflow_check_element

#define mem_overflow_check_element (   mem)

Definition at line 447 of file mem.c.

◆ mem_overflow_init_element

#define mem_overflow_init_element (   mem,
  size 
)

Definition at line 446 of file mem.c.

◆ MEM_SANITY

#define MEM_SANITY ( )

Definition at line 427 of file mem.c.

◆ MEM_SANITY_OFFSET

#define MEM_SANITY_OFFSET   0

Definition at line 82 of file mem.c.

◆ MEM_SANITY_OVERHEAD

#define MEM_SANITY_OVERHEAD   0

Definition at line 83 of file mem.c.

◆ MEM_SIZE_ALIGNED

#define MEM_SIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(MEM_SIZE)

Definition at line 371 of file mem.c.

◆ MEM_STATS_DEC_USED_LOCKED

#define MEM_STATS_DEC_USED_LOCKED (   x,
  y 
)    SYS_ARCH_LOCKED(MEM_STATS_DEC_USED(x, y))

Definition at line 76 of file mem.c.

◆ MEM_STATS_INC_LOCKED

#define MEM_STATS_INC_LOCKED (   x)    SYS_ARCH_LOCKED(MEM_STATS_INC(x))

Definition at line 74 of file mem.c.

◆ MEM_STATS_INC_USED_LOCKED

#define MEM_STATS_INC_USED_LOCKED (   x,
  y 
)    SYS_ARCH_LOCKED(MEM_STATS_INC_USED(x, y))

Definition at line 75 of file mem.c.

◆ MIN_SIZE

#define MIN_SIZE   12

All allocated blocks will be MIN_SIZE bytes big, at least! MIN_SIZE can be overridden to suit your needs. Smaller values save space, larger values could prevent too small blocks to fragment the RAM too much.

Definition at line 366 of file mem.c.

◆ MIN_SIZE_ALIGNED

#define MIN_SIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(MIN_SIZE)

Definition at line 369 of file mem.c.

◆ SIZEOF_STRUCT_MEM

#define SIZEOF_STRUCT_MEM   LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))

Definition at line 370 of file mem.c.

Function Documentation

◆ LWIP_DECLARE_MEMORY_ALIGNED()

LWIP_DECLARE_MEMORY_ALIGNED ( ram_heap  ,
MEM_SIZE_ALIGNED 2U *SIZEOF_STRUCT_MEM 
)

If you want to relocate the heap to external memory, simply define LWIP_RAM_HEAP_POINTER as a void-pointer to that location. If so, make sure the memory at that location is big enough (see below on how that space is calculated). the heap. we need one struct mem at the end and some room for alignment

◆ mem_calloc()

void * mem_calloc ( mem_size_t  count,
mem_size_t  size 
)

Contiguously allocates enough space for count objects that are size bytes of memory each and returns a pointer to the allocated memory.

The allocated memory is filled with bytes of value zero.

Parameters
countnumber of objects to allocate
sizesize of the objects to allocate
Returns
pointer to allocated memory / NULL pointer if there is an error

Definition at line 999 of file mem.c.

1000{
1001 void *p;
1002 size_t alloc_size = (size_t)count * (size_t)size;
1003
1004 if ((size_t)(mem_size_t)alloc_size != alloc_size) {
1005 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_calloc: could not allocate %"SZT_F" bytes\n", alloc_size));
1006 return NULL;
1007 }
1008
1009 /* allocate 'count' objects of size 'size' */
1010 p = mem_malloc((mem_size_t)alloc_size);
1011 if (p) {
1012 /* zero the memory */
1013 memset(p, 0, alloc_size);
1014 }
1015 return p;
1016}
#define NULL
Definition: types.h:112
__kernel_size_t size_t
Definition: linux.h:237
void * mem_malloc(mem_size_t size_in)
Definition: mem.c:831
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
u16_t mem_size_t
Definition: mem.h:67
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat p
Definition: glext.h:8902
#define SZT_F
Definition: arch.h:171
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
#define MEM_DEBUG
Definition: opt.h:3413
#define memset(x, y, z)
Definition: compat.h:39

Referenced by bridgeif_fdb_init().

◆ mem_free()

void mem_free ( void rmem)

Put a struct mem back on the heap

Parameters
rmemis the data portion of a struct mem as returned by a previous call to mem_malloc()

Definition at line 617 of file mem.c.

618{
619 struct mem *mem;
621
622 if (rmem == NULL) {
623 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
624 return;
625 }
626 if ((((mem_ptr_t)rmem) & (MEM_ALIGNMENT - 1)) != 0) {
627 LWIP_MEM_ILLEGAL_FREE("mem_free: sanity check alignment");
628 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: sanity check alignment\n"));
629 /* protect mem stats from concurrent access */
630 MEM_STATS_INC_LOCKED(illegal);
631 return;
632 }
633
634 /* Get the corresponding struct mem: */
635 /* cast through void* to get rid of alignment warnings */
636 mem = (struct mem *)(void *)((u8_t *)rmem - (SIZEOF_STRUCT_MEM + MEM_SANITY_OFFSET));
637
638 if ((u8_t *)mem < ram || (u8_t *)rmem + MIN_SIZE_ALIGNED > (u8_t *)ram_end) {
639 LWIP_MEM_ILLEGAL_FREE("mem_free: illegal memory");
640 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
641 /* protect mem stats from concurrent access */
642 MEM_STATS_INC_LOCKED(illegal);
643 return;
644 }
645#if MEM_OVERFLOW_CHECK
647#endif
648 /* protect the heap from concurrent access */
650 /* mem has to be in a used state */
651 if (!mem->used) {
652 LWIP_MEM_ILLEGAL_FREE("mem_free: illegal memory: double free");
654 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory: double free?\n"));
655 /* protect mem stats from concurrent access */
656 MEM_STATS_INC_LOCKED(illegal);
657 return;
658 }
659
660 if (!mem_link_valid(mem)) {
661 LWIP_MEM_ILLEGAL_FREE("mem_free: illegal memory: non-linked: double free");
663 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory: non-linked: double free?\n"));
664 /* protect mem stats from concurrent access */
665 MEM_STATS_INC_LOCKED(illegal);
666 return;
667 }
668
669 /* mem is now unused. */
670 mem->used = 0;
671
672 if (mem < lfree) {
673 /* the newly freed struct is now the lowest */
674 lfree = mem;
675 }
676
678
679 /* finally, see if prev or next are free also */
681 MEM_SANITY();
682#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
683 mem_free_count = 1;
684#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
686}
static int used
Definition: adh-main.c:39
#define MEM_ALIGNMENT
Definition: d3d9_helpers.c:15
static struct mem *LWIP_MEM_LFREE_VOLATILE lfree
Definition: mem.c:421
#define MEM_STATS_INC_LOCKED(x)
Definition: mem.c:74
#define mem_overflow_check_element(mem)
Definition: mem.c:447
#define LWIP_MEM_FREE_DECL_PROTECT()
Definition: mem.c:409
static int mem_link_valid(struct mem *mem)
Definition: mem.c:551
static void plug_holes(struct mem *mem)
Definition: mem.c:474
#define MEM_SANITY()
Definition: mem.c:427
#define LWIP_MEM_ILLEGAL_FREE(msg)
Definition: mem.c:71
#define LWIP_MEM_FREE_UNPROTECT()
Definition: mem.c:411
static u8_t * ram
Definition: mem.c:384
#define MEM_SANITY_OFFSET
Definition: mem.c:82
#define SIZEOF_STRUCT_MEM
Definition: mem.c:370
static struct mem * ram_end
Definition: mem.c:386
#define LWIP_MEM_FREE_PROTECT()
Definition: mem.c:410
uint8_t u8_t
Definition: arch.h:125
uintptr_t mem_ptr_t
Definition: arch.h:135
#define LWIP_DBG_TRACE
Definition: debug.h:83
#define LWIP_DBG_LEVEL_SEVERE
Definition: debug.h:59
#define MEM_STATS_DEC_USED(x, y)
Definition: stats.h:398
Definition: mem.c:349
mem_size_t next
Definition: mem.c:351
u8_t used
Definition: mem.c:355

◆ mem_init()

void mem_init ( void  )

Zero the heap and initialize start, end and lowest-free

Definition at line 516 of file mem.c.

517{
518 struct mem *mem;
519
520 LWIP_ASSERT("Sanity check alignment",
521 (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT - 1)) == 0);
522
523 /* align the heap */
525 /* initialize the start of the heap */
526 mem = (struct mem *)(void *)ram;
528 mem->prev = 0;
529 mem->used = 0;
530 /* initialize the end of the heap */
532 ram_end->used = 1;
535 MEM_SANITY();
536
537 /* initialize the lowest-free pointer to the start of the heap */
538 lfree = (struct mem *)(void *)ram;
539
541
542 if (sys_mutex_new(&mem_mutex) != ERR_OK) {
543 LWIP_ASSERT("failed to create mem_mutex", 0);
544 }
545}
static int avail
Definition: adh-main.c:39
static sys_mutex_t mem_mutex
Definition: mem.c:390
static struct mem * ptr_to_mem(mem_size_t ptr)
Definition: mem.c:451
#define LWIP_RAM_HEAP_POINTER
Definition: mem.c:380
#define MEM_SIZE_ALIGNED
Definition: mem.c:371
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define LWIP_MEM_ALIGN(addr)
Definition: arch.h:294
@ ERR_OK
Definition: err.h:55
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.c:149
#define MEM_STATS_AVAIL(x, y)
Definition: stats.h:395
mem_size_t prev
Definition: mem.c:353

Referenced by lwip_init().

◆ mem_link_valid()

static int mem_link_valid ( struct mem mem)
static

Definition at line 551 of file mem.c.

552{
553 struct mem *nmem, *pmem;
554 mem_size_t rmem_idx;
555 rmem_idx = mem_to_ptr(mem);
556 nmem = ptr_to_mem(mem->next);
557 pmem = ptr_to_mem(mem->prev);
559 ((mem->prev != rmem_idx) && (pmem->next != rmem_idx)) ||
560 ((nmem != ram_end) && (nmem->prev != rmem_idx))) {
561 return 0;
562 }
563 return 1;
564}
static mem_size_t mem_to_ptr(void *mem)
Definition: mem.c:457

Referenced by mem_free().

◆ mem_malloc()

void * mem_malloc ( mem_size_t  size_in)

Allocate a block of memory with a minimum of 'size' bytes.

Parameters
size_inis the minimum size of the requested block in bytes.
Returns
pointer to allocated memory or NULL if no free memory was found.

Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT).

Definition at line 831 of file mem.c.

832{
833 mem_size_t ptr, ptr2, size;
834 struct mem *mem, *mem2;
835#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
836 u8_t local_mem_free_count = 0;
837#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
839
840 if (size_in == 0) {
841 return NULL;
842 }
843
844 /* Expand the size of the allocated memory region so that we can
845 adjust for alignment. */
847 if (size < MIN_SIZE_ALIGNED) {
848 /* every data block must be at least MIN_SIZE_ALIGNED long */
850 }
851#if MEM_OVERFLOW_CHECK
852 size += MEM_SANITY_REGION_BEFORE_ALIGNED + MEM_SANITY_REGION_AFTER_ALIGNED;
853#endif
854 if ((size > MEM_SIZE_ALIGNED) || (size < size_in)) {
855 return NULL;
856 }
857
858 /* protect the heap from concurrent access */
861#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
862 /* run as long as a mem_free disturbed mem_malloc or mem_trim */
863 do {
864 local_mem_free_count = 0;
865#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
866
867 /* Scan through the heap searching for a free block that is big enough,
868 * beginning with the lowest free block.
869 */
871 ptr = ptr_to_mem(ptr)->next) {
872 mem = ptr_to_mem(ptr);
873#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
874 mem_free_count = 0;
876 /* allow mem_free or mem_trim to run */
878 if (mem_free_count != 0) {
879 /* If mem_free or mem_trim have run, we have to restart since they
880 could have altered our current struct mem. */
881 local_mem_free_count = 1;
882 break;
883 }
884#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
885
886 if ((!mem->used) &&
887 (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
888 /* mem is not used and at least perfect fit is possible:
889 * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
890
892 /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
893 * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
894 * -> split large block, create empty remainder,
895 * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
896 * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
897 * struct mem would fit in but no data between mem2 and mem2->next
898 * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
899 * region that couldn't hold data, but when mem->next gets freed,
900 * the 2 regions would be combined, resulting in more free memory
901 */
902 ptr2 = (mem_size_t)(ptr + SIZEOF_STRUCT_MEM + size);
903 LWIP_ASSERT("invalid next ptr",ptr2 != MEM_SIZE_ALIGNED);
904 /* create mem2 struct */
905 mem2 = ptr_to_mem(ptr2);
906 mem2->used = 0;
907 mem2->next = mem->next;
908 mem2->prev = ptr;
909 /* and insert it between mem and mem->next */
910 mem->next = ptr2;
911 mem->used = 1;
912
913 if (mem2->next != MEM_SIZE_ALIGNED) {
914 ptr_to_mem(mem2->next)->prev = ptr2;
915 }
917 } else {
918 /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
919 * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
920 * take care of this).
921 * -> near fit or exact fit: do not split, no mem2 creation
922 * also can't move mem->next directly behind mem, since mem->next
923 * will always be used at this point!
924 */
925 mem->used = 1;
927 }
928#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
929mem_malloc_adjust_lfree:
930#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
931 if (mem == lfree) {
932 struct mem *cur = lfree;
933 /* Find next free block after mem and update lowest free pointer */
934 while (cur->used && cur != ram_end) {
935#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
936 mem_free_count = 0;
938 /* prevent high interrupt latency... */
940 if (mem_free_count != 0) {
941 /* If mem_free or mem_trim have run, we have to restart since they
942 could have altered our current struct mem or lfree. */
943 goto mem_malloc_adjust_lfree;
944 }
945#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
946 cur = ptr_to_mem(cur->next);
947 }
948 lfree = cur;
949 LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
950 }
953 LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
955 LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
957 LWIP_ASSERT("mem_malloc: sanity check alignment",
958 (((mem_ptr_t)mem) & (MEM_ALIGNMENT - 1)) == 0);
959
960#if MEM_OVERFLOW_CHECK
962#endif
963 MEM_SANITY();
965 }
966 }
967#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
968 /* if we got interrupted by a mem_free, try again */
969 } while (local_mem_free_count != 0);
970#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
974 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
975 return NULL;
976}
#define S16_F
Definition: cc.h:20
#define LWIP_MEM_ALLOC_DECL_PROTECT()
Definition: mem.c:413
#define LWIP_MEM_ALLOC_PROTECT()
Definition: mem.c:414
#define mem_overflow_init_element(mem, size)
Definition: mem.c:446
#define MIN_SIZE_ALIGNED
Definition: mem.c:369
#define LWIP_MEM_ALLOC_UNPROTECT()
Definition: mem.c:415
FxCollectionEntry * cur
int16_t s16_t
Definition: arch.h:128
#define LWIP_MEM_ALIGN_SIZE(size)
Definition: arch.h:279
void sys_mutex_lock(sys_mutex_t *mutex)
Definition: sys_arch.c:173
void sys_mutex_unlock(sys_mutex_t *mutex)
Definition: sys_arch.c:185
static PVOID ptr
Definition: dispmode.c:27
#define err(...)
#define MEM_STATS_INC(x)
Definition: stats.h:396
#define MEM_STATS_INC_USED(x, y)
Definition: stats.h:397

Referenced by do_memp_malloc_pool(), malloc_keep_x(), mem_calloc(), pbuf_alloc(), slipif_init(), and START_TEST().

◆ mem_to_ptr()

static mem_size_t mem_to_ptr ( void mem)
static

Definition at line 457 of file mem.c.

458{
459 return (mem_size_t)((u8_t *)mem - ram);
460}

Referenced by mem_link_valid(), mem_malloc(), mem_trim(), and plug_holes().

◆ mem_trim()

void * mem_trim ( void rmem,
mem_size_t  new_size 
)

Shrink memory returned by mem_malloc().

Parameters
rmempointer to memory allocated by mem_malloc the is to be shrunk
new_sizerequired size after shrinking (needs to be smaller than or equal to the previous size)
Returns
for compatibility reasons: is always == rmem, at the moment or NULL if newsize is > old size, in which case rmem is NOT touched or freed!

Definition at line 699 of file mem.c.

700{
701 mem_size_t size, newsize;
702 mem_size_t ptr, ptr2;
703 struct mem *mem, *mem2;
704 /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
706
707 /* Expand the size of the allocated memory region so that we can
708 adjust for alignment. */
709 newsize = (mem_size_t)LWIP_MEM_ALIGN_SIZE(new_size);
710 if (newsize < MIN_SIZE_ALIGNED) {
711 /* every data block must be at least MIN_SIZE_ALIGNED long */
712 newsize = MIN_SIZE_ALIGNED;
713 }
714#if MEM_OVERFLOW_CHECK
715 newsize += MEM_SANITY_REGION_BEFORE_ALIGNED + MEM_SANITY_REGION_AFTER_ALIGNED;
716#endif
717 if ((newsize > MEM_SIZE_ALIGNED) || (newsize < new_size)) {
718 return NULL;
719 }
720
721 LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
722 (u8_t *)rmem < (u8_t *)ram_end);
723
724 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
725 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
726 /* protect mem stats from concurrent access */
727 MEM_STATS_INC_LOCKED(illegal);
728 return rmem;
729 }
730 /* Get the corresponding struct mem ... */
731 /* cast through void* to get rid of alignment warnings */
732 mem = (struct mem *)(void *)((u8_t *)rmem - (SIZEOF_STRUCT_MEM + MEM_SANITY_OFFSET));
733#if MEM_OVERFLOW_CHECK
735#endif
736 /* ... and its offset pointer */
737 ptr = mem_to_ptr(mem);
738
740 LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
741 if (newsize > size) {
742 /* not supported */
743 return NULL;
744 }
745 if (newsize == size) {
746 /* No change in size, simply return */
747 return rmem;
748 }
749
750 /* protect the heap from concurrent access */
752
753 mem2 = ptr_to_mem(mem->next);
754 if (mem2->used == 0) {
755 /* The next struct is unused, we can simply move it at little */
757 LWIP_ASSERT("invalid next ptr", mem->next != MEM_SIZE_ALIGNED);
758 /* remember the old next pointer */
759 next = mem2->next;
760 /* create new struct mem which is moved directly after the shrunk mem */
761 ptr2 = (mem_size_t)(ptr + SIZEOF_STRUCT_MEM + newsize);
762 if (lfree == mem2) {
763 lfree = ptr_to_mem(ptr2);
764 }
765 mem2 = ptr_to_mem(ptr2);
766 mem2->used = 0;
767 /* restore the next pointer */
768 mem2->next = next;
769 /* link it back to mem */
770 mem2->prev = ptr;
771 /* link mem to it */
772 mem->next = ptr2;
773 /* last thing to restore linked list: as we have moved mem2,
774 * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
775 * the end of the heap */
776 if (mem2->next != MEM_SIZE_ALIGNED) {
777 ptr_to_mem(mem2->next)->prev = ptr2;
778 }
779 MEM_STATS_DEC_USED(used, (size - newsize));
780 /* no need to plug holes, we've already done that */
781 } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
782 /* Next struct is used but there's room for another struct mem with
783 * at least MIN_SIZE_ALIGNED of data.
784 * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
785 * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
786 * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
787 * region that couldn't hold data, but when mem->next gets freed,
788 * the 2 regions would be combined, resulting in more free memory */
789 ptr2 = (mem_size_t)(ptr + SIZEOF_STRUCT_MEM + newsize);
790 LWIP_ASSERT("invalid next ptr", mem->next != MEM_SIZE_ALIGNED);
791 mem2 = ptr_to_mem(ptr2);
792 if (mem2 < lfree) {
793 lfree = mem2;
794 }
795 mem2->used = 0;
796 mem2->next = mem->next;
797 mem2->prev = ptr;
798 mem->next = ptr2;
799 if (mem2->next != MEM_SIZE_ALIGNED) {
800 ptr_to_mem(mem2->next)->prev = ptr2;
801 }
802 MEM_STATS_DEC_USED(used, (size - newsize));
803 /* the original mem->next is used, so no need to plug holes! */
804 }
805 /* else {
806 next struct mem is used but size between mem and mem2 is not big enough
807 to create another struct mem
808 -> don't do anyhting.
809 -> the remaining space stays unused since it is too small
810 } */
811#if MEM_OVERFLOW_CHECK
813#endif
814 MEM_SANITY();
815#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
816 mem_free_count = 1;
817#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
819 return rmem;
820}
#define MEM_SANITY_OVERHEAD
Definition: mem.c:83
static unsigned __int64 next
Definition: rand_nt.c:6

Referenced by pbuf_realloc(), and START_TEST().

◆ plug_holes()

static void plug_holes ( struct mem mem)
static

"Plug holes" by combining adjacent empty struct mems. After this function is through, there should not exist one empty struct mem pointing to another empty struct mem.

Parameters
memthis points to a struct mem which just has been freed

Definition at line 474 of file mem.c.

475{
476 struct mem *nmem;
477 struct mem *pmem;
478
479 LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
480 LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
481 LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
482
483 /* plug hole forward */
484 LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
485
486 nmem = ptr_to_mem(mem->next);
487 if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
488 /* if mem->next is unused and not end of ram, combine mem and mem->next */
489 if (lfree == nmem) {
490 lfree = mem;
491 }
492 mem->next = nmem->next;
493 if (nmem->next != MEM_SIZE_ALIGNED) {
494 ptr_to_mem(nmem->next)->prev = mem_to_ptr(mem);
495 }
496 }
497
498 /* plug hole backward */
499 pmem = ptr_to_mem(mem->prev);
500 if (pmem != mem && pmem->used == 0) {
501 /* if mem->prev is unused, combine mem and mem->prev */
502 if (lfree == mem) {
503 lfree = pmem;
504 }
505 pmem->next = mem->next;
506 if (mem->next != MEM_SIZE_ALIGNED) {
507 ptr_to_mem(mem->next)->prev = mem_to_ptr(pmem);
508 }
509 }
510}

Referenced by mem_free().

◆ ptr_to_mem()

static struct mem * ptr_to_mem ( mem_size_t  ptr)
static

Definition at line 451 of file mem.c.

452{
453 return (struct mem *)(void *)&ram[ptr];
454}

Referenced by mem_init(), mem_link_valid(), mem_malloc(), mem_trim(), and plug_holes().

Variable Documentation

◆ lfree

pointer to the lowest free block, this is used for faster search

Definition at line 421 of file mem.c.

Referenced by mem_free(), mem_init(), mem_malloc(), mem_trim(), and plug_holes().

◆ mem_mutex

sys_mutex_t mem_mutex
static

concurrent access protection

Definition at line 390 of file mem.c.

Referenced by mem_init(), and mem_malloc().

◆ ram

u8_t* ram
static

pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array

Definition at line 384 of file mem.c.

Referenced by mem_free(), mem_init(), mem_to_ptr(), mem_trim(), plug_holes(), and ptr_to_mem().

◆ ram_end

struct mem* ram_end
static

the last entry, always unused!

Definition at line 386 of file mem.c.

Referenced by mem_free(), mem_init(), mem_link_valid(), mem_malloc(), mem_trim(), and plug_holes().