1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

picolibc: enable multiple heaps

We can simply re-use the same code from newlib.
This commit is contained in:
Benjamin Valentin 2020-08-24 20:35:01 +02:00
parent 53187c5ef7
commit 28d40eae6f
2 changed files with 103 additions and 6 deletions

View File

@ -11,14 +11,10 @@ endif
ifeq (1,$(USE_PICOLIBC))
LINKFLAGS += -specs=picolibc.specs
# RIOT uses _sheap and _eheap for heap start and end, PicoLIBC uses
# __heap_start and __heap_end. This glues these different names together.
LINKFLAGS += -Wl,--defsym=__heap_end=_eheap
LINKFLAGS += -Wl,--defsym=__heap_start=_sheap
CFLAGS += -specs=picolibc.specs
ifeq (,$(filter printf_float scanf_float,$(USEMODULE)))
CFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
LINKFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
CFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
LINKFLAGS += -DPICOLIBC_INTEGER_PRINTF_SCANF
endif
endif

View File

@ -28,6 +28,81 @@
#include "periph/pm.h"
#include "stdio_base.h"
#ifndef NUM_HEAPS
#define NUM_HEAPS 1
#endif
/**
* @brief manage the heap
*/
extern char _sheap; /* start of the heap */
extern char _eheap; /* end of the heap */
#define __eheap &_eheap
/**
* @brief Additional heap sections that may be defined in the linkerscript.
*
* The compiler should not generate references to those symbols if
* they are not used, so only provide them if additional memory sections
* that can be used as heap are available.
* @{
*/
extern char _sheap1;
extern char _eheap1;
extern char _sheap2;
extern char _eheap2;
extern char _sheap3;
extern char _eheap3;
/* @} */
struct heap {
char* start;
char* end;
};
static char *heap_top[NUM_HEAPS] = {
&_sheap,
#if NUM_HEAPS > 1
&_sheap1,
#endif
#if NUM_HEAPS > 2
&_sheap2,
#endif
#if NUM_HEAPS > 3
&_sheap3,
#endif
#if NUM_HEAPS > 4
#error "Unsupported NUM_HEAPS value, edit newlib_syscalls_default/syscalls.c to add more heaps."
#endif
};
static const struct heap heaps[NUM_HEAPS] = {
{
.start = &_sheap,
.end = __eheap
},
#if NUM_HEAPS > 1
{
.start = &_sheap1,
.end = &_eheap1
},
#endif
#if NUM_HEAPS > 2
{
.start = &_sheap2,
.end = &_eheap2
},
#endif
#if NUM_HEAPS > 3
{
.start = &_sheap3,
.end = &_eheap3
},
#endif
};
/**
* @brief Exit a program without cleaning up files
*
@ -44,6 +119,32 @@ _exit(int n)
while(1);
}
/**
* @brief Allocate memory from the heap.
*
* @return pointer to the newly allocated memory on success
* @return pointer set to address `-1` on failure
*/
void *sbrk(ptrdiff_t incr)
{
void *res = (void*)UINTPTR_MAX;
unsigned int state = irq_disable();
for (unsigned i = 0; i < NUM_HEAPS; ++i) {
if ((heap_top[i] + incr > heaps[i].end) ||
(heap_top[i] + incr < heaps[i].start)) {
continue;
}
res = heap_top[i];
heap_top[i] += incr;
break;
}
irq_restore(state);
return res;
}
/**
* @brief Send a signal to a thread
*