libc: permit users to supply their own malloc.

Severely memory constrained systems with known allocation patterns can
benefit from providing their own implementation of malloc with
specifically tuned bucket sizes. Provide a switch to allow users to
replace the default malloc implementation with their own.

Signed-off-by: Josh Gao <josh@jmgao.dev>
This commit is contained in:
Josh Gao 2019-12-10 00:26:32 -08:00 committed by Maureen Helm
commit c0026346a3
2 changed files with 54 additions and 23 deletions

View file

@ -80,6 +80,15 @@ endif # NEWLIB_LIBC
if MINIMAL_LIBC if MINIMAL_LIBC
config MINIMAL_LIBC_MALLOC
bool "Enable minimal libc malloc implementation"
default y
help
Enable the minimal libc's implementation of malloc, free, and realloc.
Disable if you wish to provide your own implementations of these functions.
if MINIMAL_LIBC_MALLOC
config MINIMAL_LIBC_MALLOC_ARENA_SIZE config MINIMAL_LIBC_MALLOC_ARENA_SIZE
int "Size of the minimal libc malloc arena" int "Size of the minimal libc malloc arena"
default 0 default 0
@ -88,6 +97,22 @@ config MINIMAL_LIBC_MALLOC_ARENA_SIZE
malloc() implementation. This size value must be compatible with malloc() implementation. This size value must be compatible with
a sys_mem_pool definition with nmax of 1 and minsz of 16. a sys_mem_pool definition with nmax of 1 and minsz of 16.
endif
config MINIMAL_LIBC_CALLOC
bool "Enable minimal libc trivial calloc implementation"
default y
help
Enable the minimal libc's trivial implementation of calloc, which
forwards to malloc and memset.
config MINIMAL_LIBC_REALLOCARRAY
bool "Enable minimal libc trivial reallocarray implementation"
default y
help
Enable the minimal libc's trivial implementation of reallocarray, which
forwards to realloc.
config MINIMAL_LIBC_LL_PRINTF config MINIMAL_LIBC_LL_PRINTF
bool "Build with minimal libc long long printf" if !64BIT bool "Build with minimal libc long long printf" if !64BIT
default y if 64BIT default y if 64BIT

View file

@ -17,6 +17,8 @@
#include <logging/log.h> #include <logging/log.h>
LOG_MODULE_DECLARE(os); LOG_MODULE_DECLARE(os);
#ifdef CONFIG_MINIMAL_LIBC_MALLOC
#if (CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0) #if (CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0)
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
K_APPMEM_PARTITION_DEFINE(z_malloc_partition); K_APPMEM_PARTITION_DEFINE(z_malloc_partition);
@ -62,29 +64,6 @@ void *malloc(size_t size)
} }
#endif #endif
void free(void *ptr)
{
sys_mem_pool_free(ptr);
}
void *calloc(size_t nmemb, size_t size)
{
void *ret;
if (size_mul_overflow(nmemb, size, &size)) {
errno = ENOMEM;
return NULL;
}
ret = malloc(size);
if (ret != NULL) {
(void)memset(ret, 0, size);
}
return ret;
}
void *realloc(void *ptr, size_t requested_size) void *realloc(void *ptr, size_t requested_size)
{ {
void *new_ptr; void *new_ptr;
@ -116,7 +95,33 @@ void *realloc(void *ptr, size_t requested_size)
return new_ptr; return new_ptr;
} }
void free(void *ptr)
{
sys_mem_pool_free(ptr);
}
#endif /* CONFIG_MINIMAL_LIBC_MALLOC */
#ifdef CONFIG_MINIMAL_LIBC_CALLOC
void *calloc(size_t nmemb, size_t size)
{
void *ret;
if (size_mul_overflow(nmemb, size, &size)) {
errno = ENOMEM;
return NULL;
}
ret = malloc(size);
if (ret != NULL) {
(void)memset(ret, 0, size);
}
return ret;
}
#endif /* CONFIG_MINIMAL_LIBC_CALLOC */
#ifdef CONFIG_MINIMAL_LIBC_REALLOCARRAY
void *reallocarray(void *ptr, size_t nmemb, size_t size) void *reallocarray(void *ptr, size_t nmemb, size_t size)
{ {
if (size_mul_overflow(nmemb, size, &size)) { if (size_mul_overflow(nmemb, size, &size)) {
@ -125,3 +130,4 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size)
} }
return realloc(ptr, size); return realloc(ptr, size);
} }
#endif /* CONFIG_MINIMAL_LIBC_REALLOCARRAY */