Various fixes around Companion trainer mode (#7116)
[opentx.git] / radio / src / bin_allocator.cpp
blob8d1bfd477c601f72c9edf1e223907efeecfe3718
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include <stdlib.h>
22 #include <string.h>
23 #include "opentx.h"
24 #include "bin_allocator.h"
27 BinAllocator_slots1 slots1;
28 BinAllocator_slots2 slots2;
30 #if defined(DEBUG)
31 int SimulateMallocFailure = 0; //set this to simulate allocation failure
32 #endif
34 bool bin_free(void * ptr)
36 //return TRUE if ours
37 return slots1.free(ptr) || slots2.free(ptr);
40 void * bin_malloc(size_t size) {
41 //try to allocate from our space
42 void * res = slots1.malloc(size);
43 return res ? res : slots2.malloc(size);
46 void * bin_realloc(void * ptr, size_t size)
48 if (ptr == 0) {
49 //no previous data, try our malloc
50 return bin_malloc(size);
52 else {
53 if (! (slots1.is_member(ptr) || slots2.is_member(ptr)) ) {
54 // not our data, leave it to libc realloc
55 return 0;
58 //we have existing data
59 // if it fits in current slot, return it
60 // TODO if new size is smaller, try to relocate in smaller slot
61 if ( slots1.can_fit(ptr, size) ) {
62 // TRACE("OUR realloc %p[%lu] fits in slot1", ptr, size);
63 return ptr;
65 if ( slots2.can_fit(ptr, size) ) {
66 // TRACE("OUR realloc %p[%lu] fits in slot2", ptr, size);
67 return ptr;
70 //we need a bigger slot
71 void * res = bin_malloc(size);
72 if (res == 0) {
73 // we don't have the space, use libc malloc
74 // TRACE("bin_malloc [%lu] FAILURE", size);
75 res = malloc(size);
76 if (res == 0) {
77 TRACE("libc malloc [%lu] FAILURE", size);
78 return 0;
81 //copy data
82 memcpy(res, ptr, slots1.size(ptr) + slots2.size(ptr));
83 bin_free(ptr);
84 return res;
89 void *bin_l_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
91 (void)ud; (void)osize; /* not used */
92 if (nsize == 0) {
93 if (ptr) { // avoid a bunch of NULL pointer free calls
94 if (!bin_free(ptr)) {
95 // not our range, use libc allocator
96 // TRACE("libc free %p", ptr);
97 free(ptr);
100 return nullptr;
102 else {
103 #if defined(DEBUG)
104 if (SimulateMallocFailure < 0 ) {
105 //delayed failure
106 if (++SimulateMallocFailure == 0) {
107 SimulateMallocFailure = 1;
110 if ( SimulateMallocFailure > 0) {
111 // simulate one malloc failure
112 TRACE("bin_l_alloc(): simulating malloc failure at %p[%lu]", ptr, nsize);
113 return 0;
115 #endif // #if defined(DEBUG)
116 // try our allocator, if it fails use libc allocator
117 void * res = bin_realloc(ptr, nsize);
118 if (res && ptr) {
119 // TRACE("OUR realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize);
121 if (res == 0) {
122 res = realloc(ptr, nsize);
123 // TRACE("libc realloc %p[%lu] -> %p[%lu]", ptr, osize, res, nsize);
124 // if (res == 0 ){
125 // TRACE("realloc FAILURE %lu", nsize);
126 // dumpFreeMemory();
127 // }
129 return res;