diff --git a/pkg/tlsf/Makefile.dep b/pkg/tlsf/Makefile.dep new file mode 100644 index 000000000000..f83eaa710f4b --- /dev/null +++ b/pkg/tlsf/Makefile.dep @@ -0,0 +1,9 @@ +ifneq (,$(filter tlsf-malloc,$(USEMODULE))) + ifneq (,$(filter newlib,$(USEMODULE))) + USEMODULE += tlsf-malloc_newlib + else ifneq (,$(filter native,$(BOARD))) + USEMODULE += tlsf-malloc_native + else + $(warning tlsf-malloc can only be used on native or on platforms using newlib) + endif +endif diff --git a/pkg/tlsf/Makefile.include b/pkg/tlsf/Makefile.include index 632832797236..f5780a61130d 100644 --- a/pkg/tlsf/Makefile.include +++ b/pkg/tlsf/Makefile.include @@ -4,3 +4,12 @@ ifneq (,$(filter tlsf-malloc,$(USEMODULE))) INCLUDES += -I$(RIOTPKG)/tlsf/contrib/include DIRS += $(RIOTPKG)/tlsf/contrib endif + +PSEUDOMODULES += tlsf-malloc_newlib +PSEUDOMODULES += tlsf-malloc_native + +ifneq (,$(filter tlsf-malloc_newlib,$(USEMODULE))) + UNDEF += $(BINDIR)/tlsf-malloc/newlib.o +else ifneq (,$(filter tlsf-malloc_native,$(BOARD))) + UNDEF += $(BINDIR)/tlsf-malloc/native.o +endif diff --git a/pkg/tlsf/contrib/Makefile b/pkg/tlsf/contrib/Makefile index 290de6a16c8d..161477a4e393 100644 --- a/pkg/tlsf/contrib/Makefile +++ b/pkg/tlsf/contrib/Makefile @@ -1,3 +1,5 @@ -MODULE := tlsf-malloc +MODULE = tlsf-malloc +SUBMODULES = 1 +SRC = tlsf-malloc.c include $(RIOTBASE)/Makefile.base diff --git a/pkg/tlsf/contrib/include/tlsf-malloc.h b/pkg/tlsf/contrib/include/tlsf-malloc.h index e99523fc9961..943b800402bb 100644 --- a/pkg/tlsf/contrib/include/tlsf-malloc.h +++ b/pkg/tlsf/contrib/include/tlsf-malloc.h @@ -37,6 +37,7 @@ #define TLSF_MALLOC_H #include + #include "tlsf.h" #ifdef __cplusplus @@ -86,7 +87,7 @@ int tlsf_add_global_pool(void *mem, size_t bytes); * * Use for debugging purposes only. */ -tlsf_t *_tlsf_get_global_control(void); +tlsf_t _tlsf_get_global_control(void); #ifdef __cplusplus diff --git a/pkg/tlsf/contrib/native.c b/pkg/tlsf/contrib/native.c new file mode 100644 index 000000000000..9bf7421b4aae --- /dev/null +++ b/pkg/tlsf/contrib/native.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_tlsf_malloc + * @ingroup pkg + * @ingroup sys + * @{ + * @file + * + * @brief Definitions to use tlsf as malloc on native. + * @author Juan I Carrano + * + * This assumes glibc is bein used. + * see: https://www.gnu.org/software/libc/manual/html_node/Replacing-malloc.html + * + */ + +#include +#include + +#include "irq.h" +#include "tlsf.h" +#include "tlsf-malloc.h" +#include "tlsf-malloc-internal.h" + +/* TODO: Add defines for other compilers */ +#if defined(__GNUC__) && !defined(__clang__) /* Clang supports __GNUC__ but + * not the alloc_size() + * attribute */ + +#define ATTR_MALLOC __attribute__((malloc, alloc_size(1))) +#define ATTR_CALLOC __attribute__((malloc, alloc_size(1,2))) +#define ATTR_MALIGN __attribute__((alloc_align(1), alloc_size(2), malloc)) +#define ATTR_REALLOC __attribute__((alloc_size(2))) + +#else /* No GNU C -> no alias attribute */ + +#define ATTR_MALLOC +#define ATTR_CALLOC +#define ATTR_MALIGN +#define ATTR_REALLOC + +#endif /* __GNUC__ */ + +extern tlsf_t tlsf_malloc_gheap; + +/** + * Allocate a block of size "bytes" + */ +ATTR_MALLOC void *malloc(size_t bytes) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_malloc(tlsf_malloc_gheap, bytes); + + if (result == NULL) { + errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + +/** + * Allocate and clear a block of size "bytes*count" + */ +ATTR_CALLOC void *calloc(size_t count, size_t bytes) +{ + void *result = malloc(count * bytes); + + if (result != NULL) { + memset(result, 0, count * bytes); + } + return result; +} + +/** + * Allocate an aligned memory block. + */ +ATTR_MALIGN void *memalign(size_t align, size_t bytes) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_memalign(tlsf_malloc_gheap, align, bytes); + + if (result == NULL) { + errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + +/** + * Deallocate and reallocate with a different size. + */ +ATTR_REALLOC void *realloc(void *ptr, size_t size) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_realloc(tlsf_malloc_gheap, ptr, size); + + if (result == NULL) { + errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + + +/** + * Deallocate a block of data. + */ +void free(void *ptr) +{ + unsigned old_state = irq_disable(); + + tlsf_free(tlsf_malloc_gheap, ptr); + irq_restore(old_state); +} diff --git a/pkg/tlsf/contrib/newlib.c b/pkg/tlsf/contrib/newlib.c new file mode 100644 index 000000000000..c90535635c56 --- /dev/null +++ b/pkg/tlsf/contrib/newlib.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_tlsf_malloc + * @ingroup pkg + * @ingroup sys + * @{ + * @file + * + * @brief Reentrant definitions to replace newlib's malloc with TLSF. + * @author Juan I Carrano + * + * Newlib-nano implements malloc/free/etc in terms of the reentrant definitions + * in _malloc_r/_free_r/etc so the latter are the one that have to be + * overwritten. + * + */ + +#include +#include +#include + +#include "irq.h" +#include "tlsf.h" +#include "tlsf-malloc.h" +#include "tlsf-malloc-internal.h" + + +/* TODO: Add defines for other compilers */ +#if defined(__GNUC__) && !defined(__clang__) /* Clang supports __GNUC__ but + * not the alloc_size() + * attribute */ + +#define ATTR_MALLOCR __attribute__((malloc, alloc_size(2))) +#define ATTR_CALLOCR __attribute__((malloc, alloc_size(2,3))) +#define ATTR_MALIGNR __attribute__((alloc_align(2), alloc_size(3), malloc)) +#define ATTR_REALLOCR __attribute__((alloc_size(3))) + +#else /* No GNU C -> no alias attribute */ + +#define ATTR_MALLOCR +#define ATTR_CALLOCR +#define ATTR_MALIGNR +#define ATTR_REALLOCR + +#endif /* __GNUC__ */ + +/** + * Allocate a block of size "bytes" + */ +ATTR_MALLOCR void *_malloc_r(struct _reent *reent_ptr, size_t bytes) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_malloc(tlsf_malloc_gheap, bytes); + + if (result == NULL) { + reent_ptr->_errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + +/** + * Allocate and clear a block of size "bytes*count" + */ +ATTR_CALLOCR void *_calloc_r(struct _reent *reent_ptr, size_t count, size_t bytes) +{ + void *result = _malloc_r(reent_ptr, count * bytes); + + if (result != NULL) { + memset(result, 0, count * bytes); + } + return result; +} + +/** + * Allocate an aligned memory block. + */ +ATTR_MALIGNR void *_memalign_r(struct _reent *reent_ptr, size_t align, size_t bytes) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_memalign(tlsf_malloc_gheap, align, bytes); + + if (result == NULL) { + reent_ptr->_errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + +/** + * Deallocate and reallocate with a different size. + */ +ATTR_REALLOCR void *_realloc_r(struct _reent *reent_ptr, void *ptr, size_t size) +{ + unsigned old_state = irq_disable(); + void *result = tlsf_realloc(tlsf_malloc_gheap, ptr, size); + + if (result == NULL) { + reent_ptr->_errno = ENOMEM; + } + + irq_restore(old_state); + return result; +} + +/** + * Deallocate a block of data. + */ +void _free_r(struct _reent *reent_ptr, void *ptr) +{ + unsigned old_state = irq_disable(); + (void)reent_ptr; + + tlsf_free(tlsf_malloc_gheap, ptr); + irq_restore(old_state); +} + +/** + * @} + */ diff --git a/pkg/tlsf/contrib/tlsf-malloc-internal.h b/pkg/tlsf/contrib/tlsf-malloc-internal.h new file mode 100644 index 000000000000..1268877e1d0d --- /dev/null +++ b/pkg/tlsf/contrib/tlsf-malloc-internal.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014-2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +/** + * @ingroup pkg_tlsf_malloc + * @{ + * @file + * @internal + * + * @brief TLSF/malloc internal definitions + * @author Juan I Carrano + * + */ + +#ifndef TLSF_MALLOC_INTERNAL_H +#define TLSF_MALLOC_INTERNAL_H + +#include "tlsf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern tlsf_t tlsf_malloc_gheap; + +#ifdef __cplusplus +} +#endif + +#endif /* TLSF_MALLOC_INTERNAL_H */ diff --git a/pkg/tlsf/contrib/tlsf-malloc.c b/pkg/tlsf/contrib/tlsf-malloc.c index 117b5607173f..4683065b3d76 100644 --- a/pkg/tlsf/contrib/tlsf-malloc.c +++ b/pkg/tlsf/contrib/tlsf-malloc.c @@ -13,56 +13,35 @@ * @file * * @brief TLSF-based global memory allocator. - * @author René Kijewski * @author Juan I Carrano * */ #include -#include -#include "irq.h" #include "tlsf.h" #include "tlsf-malloc.h" +#include "tlsf-malloc-internal.h" /** * Global memory heap (really a collection of pools, or areas) **/ -static tlsf_t gheap = NULL; - -/* TODO: Add defines for other compilers */ -#if defined(__GNUC__) && !defined(__clang__) /* Clang supports __GNUC__ but - * not the alloc_size() - * attribute */ - -#define ATTR_MALLOC __attribute__((malloc, alloc_size(1))) -#define ATTR_CALLOC __attribute__((malloc, alloc_size(1,2))) -#define ATTR_MALIGN __attribute__((alloc_align(1), alloc_size(2), malloc)) -#define ATTR_REALLOC __attribute__((alloc_size(2))) - -#else /* No GNU C -> no alias attribute */ - -#define ATTR_MALLOC -#define ATTR_CALLOC -#define ATTR_MALIGN -#define ATTR_REALLOC - -#endif /* __GNUC__ */ +tlsf_t tlsf_malloc_gheap = NULL; int tlsf_add_global_pool(void *mem, size_t bytes) { - if (gheap == NULL) { - gheap = tlsf_create_with_pool(mem, bytes); - return gheap == NULL; + if (tlsf_malloc_gheap == NULL) { + tlsf_malloc_gheap = tlsf_create_with_pool(mem, bytes); + return tlsf_malloc_gheap == NULL; } else { - return tlsf_add_pool(gheap, mem, bytes) == NULL; + return tlsf_add_pool(tlsf_malloc_gheap, mem, bytes) == NULL; } } -tlsf_t *_tlsf_get_global_control(void) +tlsf_t _tlsf_get_global_control(void) { - return gheap; + return tlsf_malloc_gheap; } void tlsf_size_walker(void* ptr, size_t size, int used, void* user) @@ -77,67 +56,6 @@ void tlsf_size_walker(void* ptr, size_t size, int used, void* user) } } -/** - * Allocate a block of size "bytes" - */ -ATTR_MALLOC void *malloc(size_t bytes) -{ - unsigned old_state = irq_disable(); - void *result = tlsf_malloc(gheap, bytes); - - irq_restore(old_state); - return result; -} - -/** - * Allocate and clear a block of size "bytes*count" - */ -ATTR_CALLOC void *calloc(size_t count, size_t bytes) -{ - void *result = malloc(count * bytes); - - if (result) { - memset(result, 0, count * bytes); - } - return result; -} - -/** - * Allocate an aligned memory block. - */ -ATTR_MALIGN void *memalign(size_t align, size_t bytes) -{ - unsigned old_state = irq_disable(); - void *result = tlsf_memalign(gheap, align, bytes); - - irq_restore(old_state); - return result; -} - -/** - * Deallocate and reallocate with a different size. - */ -ATTR_REALLOC void *realloc(void *ptr, size_t size) -{ - unsigned old_state = irq_disable(); - void *result = tlsf_realloc(gheap, ptr, size); - - irq_restore(old_state); - return result; -} - - -/** - * Deallocate a block of data. - */ -void free(void *ptr) -{ - unsigned old_state = irq_disable(); - - tlsf_free(gheap, ptr); - irq_restore(old_state); -} - /** * @} */