mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/newlib: enable multiple heaps in _sbrk_r
Some MCUs have non-continuous memory regions. To support those, iterate over all available memory regions and allocate the first region that fits.
This commit is contained in:
parent
0d9d496618
commit
2ed0dd7405
@ -56,12 +56,79 @@
|
||||
#include "xtimer.h"
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
char *heap_top = &_sheap + 4;
|
||||
|
||||
/**
|
||||
* @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
|
||||
};
|
||||
|
||||
/* MIPS newlib crt implements _init,_fini and _exit and manages the heap */
|
||||
#ifndef __mips__
|
||||
@ -108,15 +175,22 @@ void _exit(int n)
|
||||
*/
|
||||
void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
|
||||
{
|
||||
void *res = (void*)UINTPTR_MAX;
|
||||
unsigned int state = irq_disable();
|
||||
void *res = heap_top;
|
||||
|
||||
if ((heap_top + incr > &_eheap) || (heap_top + incr < &_sheap)) {
|
||||
r->_errno = ENOMEM;
|
||||
res = (void *)-1;
|
||||
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;
|
||||
}
|
||||
else {
|
||||
heap_top += incr;
|
||||
|
||||
if (res == (void*)UINTPTR_MAX) {
|
||||
r->_errno = ENOMEM;
|
||||
}
|
||||
|
||||
irq_restore(state);
|
||||
|
Loading…
Reference in New Issue
Block a user