/* multiple heap interface, allowing for an allocator that uses multiple underlying heaps to cope with multiple memory regions on STM32 boards */ #include "AP_MultiHeap.h" #if ENABLE_HEAP #include #include /* allow up to 10 heaps */ #ifndef MAX_HEAPS #define MAX_HEAPS 10 #endif extern const AP_HAL::HAL &hal; /* create heaps with a total memory size, splitting over at most max_heaps */ bool MultiHeap::create(uint32_t total_size, uint8_t max_heaps, bool _allow_expansion, uint32_t _reserve_size) { max_heaps = MIN(MAX_HEAPS, max_heaps); if (heaps != nullptr) { // don't allow double allocation return false; } heaps = NEW_NOTHROW Heap[max_heaps]; if (heaps == nullptr) { return false; } num_heaps = max_heaps; for (uint8_t i=0; i 0) { heaps[i].hp = heap_create(alloc_size); if (heaps[i].hp != nullptr) { total_size -= alloc_size; sum_size += alloc_size; break; } alloc_size *= 0.9; } if (total_size == 0) { break; } } if (total_size != 0) { destroy(); return false; } allow_expansion = _allow_expansion; reserve_size = _reserve_size; return true; } // destroy heap void MultiHeap::destroy(void) { if (!available()) { return; } for (uint8_t i=0; iget_soft_armed()) { // only expand the available heaps when armed. When disarmed // user should fix their SCR_HEAP_SIZE parameter last_failed = true; return nullptr; } /* vehicle is armed and MultiHeap (for scripting) is out of memory. We will see if we can add a new heap from available memory if we have at least reserve_size bytes free */ const uint32_t available = hal.util->available_memory(); const uint32_t heap_overhead = 128; // conservative value, varies with HAL const uint32_t min_size = size + heap_overhead; if (available < reserve_size+min_size) { last_failed = true; return nullptr; } // round up to a minimum of 30k to allocate, and allow for heap overhead const uint32_t round_to = 30*1024U; const uint32_t alloc_size = MIN(available - reserve_size, MAX(size+heap_overhead, round_to)); if (alloc_size < min_size) { last_failed = true; return nullptr; } for (uint8_t i=0; i= new_size) { // Lua assumes that the allocator never fails when osize >= nsize // the best we can do is return the old pointer return ptr; } return nullptr; } memcpy(newp, ptr, MIN(old_size, new_size)); deallocate(ptr); return newp; } #endif // ENABLE_HEAP