ReactOS 0.4.16-dev-329-g9223134
mem.h File Reference
#include "lwip/opt.h"
Include dependency graph for mem.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MEM_SIZE_F   U16_F
 

Typedefs

typedef u16_t mem_size_t
 

Functions

void mem_init (void)
 
voidmem_trim (void *mem, mem_size_t size)
 
voidmem_malloc (mem_size_t size)
 
voidmem_calloc (mem_size_t count, mem_size_t size)
 
void mem_free (void *mem)
 

Detailed Description

Heap API

Definition in file mem.h.

Macro Definition Documentation

◆ MEM_SIZE_F

#define MEM_SIZE_F   U16_F

Definition at line 68 of file mem.h.

Typedef Documentation

◆ mem_size_t

typedef u16_t mem_size_t

Definition at line 67 of file mem.h.

Function Documentation

◆ 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_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
static mem_size_t mem_to_ptr(void *mem)
Definition: mem.c:457
#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_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().