From 0a58c80b56c8f9e806bb5b59cfe0c5d209e1d41f Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 26 Sep 2019 16:07:48 +0300 Subject: [PATCH] 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. --- platform/source/mbed_retarget.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/platform/source/mbed_retarget.cpp b/platform/source/mbed_retarget.cpp index c4428544d9..2038c1adad 100644 --- a/platform/source/mbed_retarget.cpp +++ b/platform/source/mbed_retarget.cpp @@ -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. */