Tighten GCC 2-region _sbrk

When moving to the second heap region due to overflowing the first
region, the `_sbrk` implementation assumed the allocation would fit in
the second region, and didn't check for that overflowing too.

Problem revealed in `stats_heap` test with GCC 8 on K64F - the allocation
attempt for 1GiB crashed, as `_sbrk` indicated 1GiB was available at the
start of the second region.
second region.

Presumably older versions of newlib fault that allocation attempt before
passing to `_sbrk`.

While there, adjust the code to not use a separate static `bool`, saving
RAM. We can track with just one pointer, as order of the two regions is
fixed, and already relied on by newlib.
pull/11572/head
Kevin Bracey 2019-09-26 16:07:48 +03:00
parent ab857c4963
commit 046379e629
1 changed files with 6 additions and 7 deletions

View File

@ -1268,7 +1268,7 @@ extern "C" WEAK void __cxa_pure_virtual(void)
extern uint32_t __mbed_sbrk_start;
extern uint32_t __mbed_krbs_start;
/* Additional RAM memory used for heap - please note this
* address should be lower address then the previous default address
* address must be lower address then the previous default address
*/
extern uint32_t __mbed_sbrk_start_0;
extern uint32_t __mbed_krbs_start_0;
@ -1276,19 +1276,18 @@ extern uint32_t __mbed_krbs_start_0;
extern "C" WEAK caddr_t _sbrk(int incr)
{
static uint32_t heap = (uint32_t) &__mbed_sbrk_start_0;
static bool once = true;
uint32_t prev_heap = heap;
uint32_t new_heap = heap + incr;
/**
* If the new address is outside the first region, start allocating from the second region.
* Jump to second region is done just once, and `static bool once` is used to keep track of that.
* If we exceed the first region, start allocating from the second region.
*/
if (once && (new_heap > (uint32_t) &__mbed_krbs_start_0)) {
once = false;
if (prev_heap <= (uint32_t) &__mbed_krbs_start_0 && new_heap > (uint32_t) &__mbed_krbs_start_0) {
prev_heap = (uint32_t) &__mbed_sbrk_start;
new_heap = prev_heap + incr;
} else if (new_heap > (uint32_t) &__mbed_krbs_start) {
}
if (new_heap > (uint32_t) &__mbed_krbs_start) {
/**
* If the new address is outside the second region, return out-of-memory.
*/