From 2671709e62e51d103dc067e86c4b0bbbffa98d41 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sat, 26 Jan 2019 10:42:36 -0600 Subject: [PATCH] mm/umm_heap: Ensure all user allocation try sbrk before fail --- mm/umm_heap/umm_calloc.c | 27 +++++++++++++++++++++++++++ mm/umm_heap/umm_memalign.c | 33 +++++++++++++++++++++++++++++++++ mm/umm_heap/umm_realloc.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/mm/umm_heap/umm_calloc.c b/mm/umm_heap/umm_calloc.c index 627843caad..e506385396 100644 --- a/mm/umm_heap/umm_calloc.c +++ b/mm/umm_heap/umm_calloc.c @@ -59,5 +59,32 @@ FAR void *calloc(size_t n, size_t elem_size) { +#ifdef CONFIG_ARCH_ADDRENV + /* Use zalloc() because it implements the sbrk() logic */ + + FAR void *ret = NULL; + + /* Verify input parameters */ + + if (n > 0 && elem_size > 0) + { + /* Assure that the following multiplication cannot overflow the size_t + * type, i.e., that: SIZE_MAX >= n * elem_size + * + * Refer to SEI CERT C Coding Standard. + */ + + if (n <= (SIZE_MAX / elem_size)) + { + ret = zalloc(n * elem_size); + } + } + + return ret; + +#else + /* Use mm_calloc() becuase it implements the clear */ + return mm_calloc(USR_HEAP, n, elem_size); +#endif } diff --git a/mm/umm_heap/umm_memalign.c b/mm/umm_heap/umm_memalign.c index 4e198cc8a9..1769d7e798 100644 --- a/mm/umm_heap/umm_memalign.c +++ b/mm/umm_heap/umm_memalign.c @@ -40,6 +40,7 @@ #include #include +#include #include @@ -64,5 +65,37 @@ FAR void *memalign(size_t alignment, size_t size) { +#ifdef CONFIG_ARCH_ADDRENV + FAR void *brkaddr; + FAR void *mem; + + /* Loop until we successfully allocate the memory or until an error + * occurs. If we fail to allocate memory on the first pass, then call + * sbrk to extend the heap by one page. This may require several + * passes if more the size of the allocation is more than one page. + * + * An alternative would be to increase the size of the heap by the + * full requested allocation in sbrk(). Then the loop should never + * execute more than twice (but more memory than we need may be + * allocated). + */ + + do + { + mem = mm_memalign(USR_HEAP, alignment, size); + if (!mem) + { + brkaddr = sbrk(size); + if (brkaddr == (FAR void *)-1) + { + return NULL; + } + } + } + while (mem == NULL); + + return mem; +#else return mm_memalign(USR_HEAP, alignment, size); +#endif } diff --git a/mm/umm_heap/umm_realloc.c b/mm/umm_heap/umm_realloc.c index e740271ca0..1de5583a4b 100644 --- a/mm/umm_heap/umm_realloc.c +++ b/mm/umm_heap/umm_realloc.c @@ -40,6 +40,7 @@ #include #include +#include #include @@ -66,5 +67,37 @@ FAR void *realloc(FAR void *oldmem, size_t size) { +#ifdef CONFIG_ARCH_ADDRENV + FAR void *brkaddr; + FAR void *mem; + + /* Loop until we successfully allocate the memory or until an error + * occurs. If we fail to allocate memory on the first pass, then call + * sbrk to extend the heap by one page. This may require several + * passes if more the size of the allocation is more than one page. + * + * An alternative would be to increase the size of the heap by the + * full requested allocation in sbrk(). Then the loop should never + * execute more than twice (but more memory than we need may be + * allocated). + */ + + do + { + mem = mm_realloc(USR_HEAP, oldmem, size); + if (!mem) + { + brkaddr = sbrk(size); + if (brkaddr == (FAR void *)-1) + { + return NULL; + } + } + } + while (mem == NULL); + + return mem; +#else return mm_realloc(USR_HEAP, oldmem, size); +#endif }