1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/tlsf/contrib/tlsf-malloc.c
Martine Lenders 82c318224b tlsf: fix for llvm
The `__GNUC__` is also available in `clang` as is just used to provide
the major version of a GNU-C compatible compiler [[1]]. So I check for
`tlsf` if the `alloc_size()` is available by using the combination of
macros as proposed here: https://stackoverflow.com/a/43205345/395687

[1]: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
2018-07-31 21:35:29 +02:00

144 lines
3.0 KiB
C

/*
* 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
* @ingroup pkg
* @ingroup sys
* @{
* @file
*
* @brief TLSF-based global memory allocator.
* @author René Kijewski
* @author Juan I Carrano
*
*/
#include <stdio.h>
#include <string.h>
#include "irq.h"
#include "tlsf.h"
#include "tlsf-malloc.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__ */
int tlsf_add_global_pool(void *mem, size_t bytes)
{
if (gheap == NULL) {
gheap = tlsf_create_with_pool(mem, bytes);
return gheap == NULL;
}
else {
return tlsf_add_pool(gheap, mem, bytes) == NULL;
}
}
tlsf_t *_tlsf_get_global_control(void)
{
return gheap;
}
void tlsf_size_walker(void* ptr, size_t size, int used, void* user)
{
printf("\t%p %s size: %u (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, ptr);
if (used) {
((tlsf_size_container_t *)user)->used += (unsigned int)size;
}
else {
((tlsf_size_container_t *)user)->free += (unsigned int)size;
}
}
/**
* 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);
}
/**
* @}
*/