| 130 | } |
| 131 | |
| 132 | void* fallback_malloc(size_t len) { |
| 133 | heap_node *p, *prev; |
| 134 | const size_t nelems = alloc_size(len); |
| 135 | mutexor mtx(&heap_mutex); |
| 136 | |
| 137 | if (NULL == freelist) |
| 138 | init_heap(); |
| 139 | |
| 140 | // Walk the free list, looking for a "big enough" chunk |
| 141 | for (p = freelist, prev = 0; p && p != list_end; |
| 142 | prev = p, p = node_from_offset(p->next_node)) { |
| 143 | |
| 144 | // Check the invariant that all heap_nodes pointers 'p' are aligned |
| 145 | // so that 'p + 1' has an alignment of at least RequiredAlignment |
| 146 | _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0, ""); |
| 147 | |
| 148 | // Calculate the number of extra padding elements needed in order |
| 149 | // to split 'p' and create a properly aligned heap_node from the tail |
| 150 | // of 'p'. We calculate aligned_nelems such that 'p->len - aligned_nelems' |
| 151 | // will be a multiple of NodesPerAlignment. |
| 152 | size_t aligned_nelems = nelems; |
| 153 | if (p->len > nelems) { |
| 154 | heap_size remaining_len = static_cast<heap_size>(p->len - nelems); |
| 155 | aligned_nelems += remaining_len % NodesPerAlignment; |
| 156 | } |
| 157 | |
| 158 | // chunk is larger and we can create a properly aligned heap_node |
| 159 | // from the tail. In this case we shorten 'p' and return the tail. |
| 160 | if (p->len > aligned_nelems) { |
| 161 | heap_node* q; |
| 162 | p->len = static_cast<heap_size>(p->len - aligned_nelems); |
| 163 | q = p + p->len; |
| 164 | q->next_node = 0; |
| 165 | q->len = static_cast<heap_size>(aligned_nelems); |
| 166 | void* ptr = q + 1; |
| 167 | _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, ""); |
| 168 | return ptr; |
| 169 | } |
| 170 | |
| 171 | // The chunk is the exact size or the chunk is larger but not large |
| 172 | // enough to split due to alignment constraints. |
| 173 | if (p->len >= nelems) { |
| 174 | if (prev == 0) |
| 175 | freelist = node_from_offset(p->next_node); |
| 176 | else |
| 177 | prev->next_node = p->next_node; |
| 178 | p->next_node = 0; |
| 179 | void* ptr = p + 1; |
| 180 | _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, ""); |
| 181 | return ptr; |
| 182 | } |
| 183 | } |
| 184 | return NULL; // couldn't find a spot big enough |
| 185 | } |
| 186 | |
| 187 | // Return the start of the next block |
| 188 | heap_node* after(struct heap_node* p) { return p + p->len; } |
no test coverage detected