From 70083168f100e8635cb1e5f3a5fcdd0362131994 Mon Sep 17 00:00:00 2001 From: wangbowen6 Date: Fri, 30 Dec 2022 16:30:55 +0800 Subject: [PATCH] mm: support custom the mm alignment and default to be 8 Signed-off-by: wangbowen6 --- mm/Kconfig | 9 +++++++++ mm/mm_heap/mm.h | 16 +++++++++------- mm/mm_heap/mm_addfreechunk.c | 2 +- mm/mm_heap/mm_checkcorruption.c | 2 +- mm/mm_heap/mm_initialize.c | 3 +-- mm/mm_heap/mm_mallinfo.c | 2 +- mm/mm_heap/mm_malloc.c | 15 ++++++++++----- mm/mm_heap/mm_memalign.c | 30 +++++++++++++++++------------- mm/mm_heap/mm_memdump.c | 2 +- mm/mm_heap/mm_realloc.c | 24 +++++++++++++++++++++--- mm/mm_heap/mm_shrinkchunk.c | 2 +- mm/mm_heap/mm_size2ndx.c | 1 + 12 files changed, 73 insertions(+), 35 deletions(-) diff --git a/mm/Kconfig b/mm/Kconfig index 5dc5c9f85d..71a95c80fa 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -61,6 +61,15 @@ config MM_KERNEL_HEAPSIZE user-mode heap. This value may need to be aligned to units of the size of the smallest memory protection region. +config MM_DFAULT_ALIGNMENT + int "Memory default alignment in bytes" + default 8 + range 0 64 + ---help--- + The memory default alignment in bytes, if this value is 0, the real + memory default alignment is equal to sizoef(uintptr), if this value + is not 0, this value must be 2^n and at least sizeof(uintptr). + config MM_SMALL bool "Small memory model" default n diff --git a/mm/mm_heap/mm.h b/mm/mm_heap/mm.h index 05c3db4bf8..adc6f24d28 100644 --- a/mm/mm_heap/mm.h +++ b/mm/mm_heap/mm.h @@ -110,7 +110,12 @@ #define MM_MAX_CHUNK (1 << MM_MAX_SHIFT) #define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1) -#define MM_GRAN_MASK (MM_MIN_CHUNK - 1) +#if CONFIG_MM_DFAULT_ALIGNMENT == 0 +# define MM_ALIGN sizeof(uintptr_t) +#else +# define MM_ALIGN CONFIG_MM_DFAULT_ALIGNMENT +#endif +#define MM_GRAN_MASK (MM_ALIGN - 1) #define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK) #define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK) @@ -138,10 +143,6 @@ #define OVERHEAD_MM_ALLOCNODE (SIZEOF_MM_ALLOCNODE - sizeof(mmsize_t)) -/* What is the size of the freenode? */ - -#define SIZEOF_MM_FREENODE sizeof(struct mm_freenode_s) - /* Get the node size */ #define SIZEOF_MM_NODE(node) ((node)->size & (~MM_MASK_BIT)) @@ -194,8 +195,9 @@ struct mm_freenode_s static_assert(SIZEOF_MM_ALLOCNODE <= MM_MIN_CHUNK, "Error size for struct mm_allocnode_s\n"); -static_assert(SIZEOF_MM_FREENODE <= MM_MIN_CHUNK, - "Error size for struct mm_freenode_s\n"); +static_assert(MM_ALIGN >= sizeof(uintptr_t) && + (MM_ALIGN & MM_GRAN_MASK) == 0, + "Error memory aligment\n"); struct mm_delaynode_s { diff --git a/mm/mm_heap/mm_addfreechunk.c b/mm/mm_heap/mm_addfreechunk.c index 335451fff7..3c7f975608 100644 --- a/mm/mm_heap/mm_addfreechunk.c +++ b/mm/mm_heap/mm_addfreechunk.c @@ -51,7 +51,7 @@ void mm_addfreechunk(FAR struct mm_heap_s *heap, size_t nodesize = SIZEOF_MM_NODE(node); int ndx; - DEBUGASSERT(nodesize >= SIZEOF_MM_FREENODE); + DEBUGASSERT(nodesize >= MM_MIN_CHUNK); DEBUGASSERT((node->size & MM_ALLOC_BIT) == 0); /* Convert the size to a nodelist index */ diff --git a/mm/mm_heap/mm_checkcorruption.c b/mm/mm_heap/mm_checkcorruption.c index 9e82833e53..30df3a1e14 100644 --- a/mm/mm_heap/mm_checkcorruption.c +++ b/mm/mm_heap/mm_checkcorruption.c @@ -50,7 +50,7 @@ static void checkcorruption_handler(FAR struct mm_allocnode_s *node, { FAR struct mm_freenode_s *fnode = (FAR void *)node; - assert(nodesize >= SIZEOF_MM_FREENODE); + assert(nodesize >= MM_MIN_CHUNK); assert(fnode->blink->flink == fnode); assert(SIZEOF_MM_NODE(fnode->blink) <= nodesize); assert(fnode->flink == NULL || diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c index c82f905634..f9ee40c156 100644 --- a/mm/mm_heap/mm_initialize.c +++ b/mm/mm_heap/mm_initialize.c @@ -139,7 +139,7 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, heap->mm_heapstart[IDX]->size = SIZEOF_MM_ALLOCNODE | MM_ALLOC_BIT; node = (FAR struct mm_freenode_s *) (heapbase + SIZEOF_MM_ALLOCNODE); - DEBUGASSERT((((uintptr_t)node + SIZEOF_MM_ALLOCNODE) % MM_MIN_CHUNK) == 0); + DEBUGASSERT((((uintptr_t)node + SIZEOF_MM_ALLOCNODE) % MM_ALIGN) == 0); node->size = heapsize - 2 * SIZEOF_MM_ALLOCNODE; heap->mm_heapend[IDX] = (FAR struct mm_allocnode_s *) (heapend - SIZEOF_MM_ALLOCNODE); @@ -204,7 +204,6 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name, heapsize -= sizeof(struct mm_heap_s); heapstart = (FAR char *)heap_adj + sizeof(struct mm_heap_s); - DEBUGASSERT(MM_MIN_CHUNK >= SIZEOF_MM_FREENODE); DEBUGASSERT(MM_MIN_CHUNK >= SIZEOF_MM_ALLOCNODE); /* Set up global variables */ diff --git a/mm/mm_heap/mm_mallinfo.c b/mm/mm_heap/mm_mallinfo.c index 34e90994bf..85dd2e3b74 100644 --- a/mm/mm_heap/mm_mallinfo.c +++ b/mm/mm_heap/mm_mallinfo.c @@ -57,7 +57,7 @@ static void mallinfo_handler(FAR struct mm_allocnode_s *node, FAR void *arg) { FAR struct mm_freenode_s *fnode = (FAR void *)node; - DEBUGASSERT(nodesize >= SIZEOF_MM_FREENODE); + DEBUGASSERT(nodesize >= MM_MIN_CHUNK); DEBUGASSERT(fnode->blink->flink == fnode); DEBUGASSERT(SIZEOF_MM_NODE(fnode->blink) <= nodesize); DEBUGASSERT(fnode->flink == NULL || diff --git a/mm/mm_heap/mm_malloc.c b/mm/mm_heap/mm_malloc.c index d03abec747..69ceb3e8d4 100644 --- a/mm/mm_heap/mm_malloc.c +++ b/mm/mm_heap/mm_malloc.c @@ -130,9 +130,15 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) #endif /* Adjust the size to account for (1) the size of the allocated node and - * (2) to make sure that it is an even multiple of our granule size. + * (2) to make sure that it is aligned with MM_ALIGN and its size is at + * least MM_MIN_CHUNK. */ + if (size < MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE) + { + size = MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE; + } + alignsize = MM_ALIGN_UP(size + OVERHEAD_MM_ALLOCNODE); if (alignsize < size) { @@ -141,8 +147,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) return NULL; } - DEBUGASSERT(alignsize >= MM_MIN_CHUNK); - DEBUGASSERT(alignsize >= SIZEOF_MM_FREENODE); + DEBUGASSERT(alignsize >= MM_ALIGN); /* We need to hold the MM mutex while we muck with the nodelist. */ @@ -204,7 +209,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) */ remaining = nodesize - alignsize; - if (remaining >= SIZEOF_MM_FREENODE) + if (remaining >= MM_MIN_CHUNK) { /* Create the remainder node */ @@ -277,6 +282,6 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) } #endif - DEBUGASSERT(ret == NULL || ((uintptr_t)ret) % MM_MIN_CHUNK == 0); + DEBUGASSERT(ret == NULL || ((uintptr_t)ret) % MM_ALIGN == 0); return ret; } diff --git a/mm/mm_heap/mm_memalign.c b/mm/mm_heap/mm_memalign.c index ee98a79c67..5833c8dcc0 100644 --- a/mm/mm_heap/mm_memalign.c +++ b/mm/mm_heap/mm_memalign.c @@ -54,7 +54,7 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, FAR struct mm_allocnode_s *node; uintptr_t rawchunk; uintptr_t alignedchunk; - size_t mask = alignment - 1; + size_t mask; size_t allocsize; size_t newsize; @@ -84,16 +84,22 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, * alignment of malloc, then just let malloc do the work. */ - if (alignment <= MM_MIN_CHUNK) + if (alignment <= MM_ALIGN) { FAR void *ptr = mm_malloc(heap, size); DEBUGASSERT(ptr == NULL || ((uintptr_t)ptr) % alignment == 0); return ptr; } + else if (alignment < MM_MIN_CHUNK) + { + alignment = MM_MIN_CHUNK; + } - /* Adjust the size to account for (1) the size of the allocated node, (2) - * to make sure that it is an even multiple of our granule size, and to - * include the alignment amount. + mask = alignment - 1; + + /* Adjust the size to account for (1) the size of the allocated node and + * (2) to make sure that it is aligned with MM_ALIGN and its size is at + * least MM_MIN_CHUNK. * * Notice that we increase the allocation size by twice the requested * alignment. We do this so that there will be at least two valid @@ -103,6 +109,11 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, * not include SIZEOF_MM_ALLOCNODE. */ + if (size < MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE) + { + size = MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE; + } + newsize = MM_ALIGN_UP(size); /* Make multiples of our granule size */ allocsize = newsize + 2 * alignment; /* Add double full alignment size */ @@ -154,13 +165,6 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, next = (FAR struct mm_allocnode_s *) ((FAR char *)node + SIZEOF_MM_NODE(node)); - /* Make sure that there is space to convert the preceding - * mm_allocnode_s into an mm_freenode_s. I think that this should - * always be true - */ - - DEBUGASSERT(alignedchunk >= rawchunk + 8); - newnode = (FAR struct mm_allocnode_s *) (alignedchunk - SIZEOF_MM_ALLOCNODE); @@ -178,7 +182,7 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, * alignment point. */ - if (precedingsize < SIZEOF_MM_FREENODE) + if (precedingsize < MM_MIN_CHUNK) { alignedchunk += alignment; newnode = (FAR struct mm_allocnode_s *) diff --git a/mm/mm_heap/mm_memdump.c b/mm/mm_heap/mm_memdump.c index a0ad5c5c7f..55c8722abd 100644 --- a/mm/mm_heap/mm_memdump.c +++ b/mm/mm_heap/mm_memdump.c @@ -95,7 +95,7 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg) { FAR struct mm_freenode_s *fnode = (FAR void *)node; - DEBUGASSERT(nodesize >= SIZEOF_MM_FREENODE); + DEBUGASSERT(nodesize >= MM_MIN_CHUNK); DEBUGASSERT(fnode->blink->flink == fnode); DEBUGASSERT(SIZEOF_MM_NODE(fnode->blink) <= nodesize); DEBUGASSERT(fnode->flink == NULL || diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c index 788fca4f48..f7dcd4f41f 100644 --- a/mm/mm_heap/mm_realloc.c +++ b/mm/mm_heap/mm_realloc.c @@ -110,9 +110,15 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, #endif /* Adjust the size to account for (1) the size of the allocated node and - * (2) to make sure that it is an even multiple of our granule size. + * (2) to make sure that it is aligned with MM_ALIGN and its size is at + * least MM_MIN_CHUNK. */ + if (size < MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE) + { + size = MM_MIN_CHUNK - OVERHEAD_MM_ALLOCNODE; + } + newsize = MM_ALIGN_UP(size + OVERHEAD_MM_ALLOCNODE); if (newsize < size) { @@ -256,6 +262,13 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, prev->flink->blink = prev->blink; } + /* Make sure the new previous node has enough space */ + + if (prevsize < takeprev + MM_MIN_CHUNK) + { + takeprev = prevsize; + } + /* Extend the node into the previous free chunk */ newnode = (FAR struct mm_allocnode_s *) @@ -270,7 +283,6 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, */ prevsize -= takeprev; - DEBUGASSERT(prevsize >= SIZEOF_MM_FREENODE); prev->size = prevsize | (prev->size & MM_MASK_BIT); nodesize += takeprev; newnode->size = nodesize | MM_ALLOC_BIT | MM_PREVFREE_BIT; @@ -323,6 +335,13 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, next->flink->blink = next->blink; } + /* Make sure the new next node has enough space */ + + if (nextsize < takenext + MM_MIN_CHUNK) + { + takenext = nextsize; + } + /* Extend the node into the next chunk */ nodesize += takenext; @@ -339,7 +358,6 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, newnode = (FAR struct mm_freenode_s *) ((FAR char *)oldnode + nodesize); newnode->size = nextsize - takenext; - DEBUGASSERT(newnode->size >= SIZEOF_MM_FREENODE); andbeyond->preceding = newnode->size; /* Add the new free node to the nodelist (with the new size) */ diff --git a/mm/mm_heap/mm_shrinkchunk.c b/mm/mm_heap/mm_shrinkchunk.c index 9360f9ab61..ce2cf16913 100644 --- a/mm/mm_heap/mm_shrinkchunk.c +++ b/mm/mm_heap/mm_shrinkchunk.c @@ -106,7 +106,7 @@ void mm_shrinkchunk(FAR struct mm_heap_s *heap, * chunk to be shrunk. */ - else if (nodesize >= size + SIZEOF_MM_FREENODE) + else if (nodesize >= size + MM_MIN_CHUNK) { FAR struct mm_freenode_s *newnode; diff --git a/mm/mm_heap/mm_size2ndx.c b/mm/mm_heap/mm_size2ndx.c index 73dad34cc5..7e022f80ec 100644 --- a/mm/mm_heap/mm_size2ndx.c +++ b/mm/mm_heap/mm_size2ndx.c @@ -44,6 +44,7 @@ int mm_size2ndx(size_t size) { + DEBUGASSERT(size >= MM_MIN_CHUNK); if (size >= MM_MAX_CHUNK) { return MM_NNODES - 1;