Files
edgetx-gx12/radio/src/bin_allocator.cpp
T

133 lines
3.5 KiB
C++

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdlib.h>
#include <string.h>
#include "opentx.h"
#include "bin_allocator.h"
BinAllocator_slots1 slots1 __SDRAM;
BinAllocator_slots2 slots2 __SDRAM;
#if defined(DEBUG)
int SimulateMallocFailure = 0; //set this to simulate allocation failure
#endif
bool bin_free(void * ptr)
{
//return TRUE if ours
return slots1.free(ptr) || slots2.free(ptr);
}
void * bin_malloc(size_t size) {
//try to allocate from our space
void * res = slots1.malloc(size);
return res ? res : slots2.malloc(size);
}
void * bin_realloc(void * ptr, size_t size)
{
if (ptr == nullptr) {
//no previous data, try our malloc
return bin_malloc(size);
}
else {
if (! (slots1.is_member(ptr) || slots2.is_member(ptr)) ) {
// not our data, leave it to libc realloc
return nullptr;
}
//we have existing data
// if it fits in current slot, return it
// TODO if new size is smaller, try to relocate in smaller slot
if ( slots1.can_fit(ptr, size) ) {
// TRACE("OUR realloc %p[%lu] fits in slot1", ptr, size);
return ptr;
}
if ( slots2.can_fit(ptr, size) ) {
// TRACE("OUR realloc %p[%lu] fits in slot2", ptr, size);
return ptr;
}
//we need a bigger slot
void * res = bin_malloc(size);
if (res == nullptr) {
// we don't have the space, use libc malloc
// TRACE("bin_malloc [%lu] FAILURE", size);
res = malloc(size);
if (res == nullptr) {
TRACE("libc malloc [%lu] FAILURE", size);
return nullptr;
}
}
//copy data
memcpy(res, ptr, slots1.size(ptr) + slots2.size(ptr));
bin_free(ptr);
return res;
}
}
void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
{
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
if (ptr) { // avoid a bunch of NULL pointer free calls
if (!bin_free(ptr)) {
// not our range, use libc allocator
// TRACE("libc free %p", ptr);
free(ptr);
}
}
return nullptr;
}
else {
#if defined(DEBUG)
if (SimulateMallocFailure < 0 ) {
//delayed failure
if (++SimulateMallocFailure == 0) {
SimulateMallocFailure = 1;
}
}
if ( SimulateMallocFailure > 0) {
// simulate one malloc failure
TRACE("bin_l_alloc(): simulating malloc failure at %p[%lu]", ptr, nsize);
return 0;
}
#endif // #if defined(DEBUG)
// try our allocator, if it fails use libc allocator
void * res = bin_realloc(ptr, nsize);
if (res && ptr) {
// TRACE("OUR realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize);
}
if (res == nullptr) {
res = realloc(ptr, nsize);
// TRACE("libc realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize);
// if (res == 0 ){
// TRACE("realloc FAILURE %lu", nsize);
// dumpFreeMemory();
// }
}
return res;
}
}