Reallocate the given block to the given size
| 1176 | |
| 1177 | //! Reallocate the given block to the given size |
| 1178 | static void* |
| 1179 | _memory_reallocate(void* p, size_t size, size_t oldsize, unsigned int flags) { |
| 1180 | if (p) { |
| 1181 | //Grab the span (always at start of span, using 64KiB alignment) |
| 1182 | span_t* span = (void*)((uintptr_t)p & SPAN_MASK); |
| 1183 | int32_t heap_id = atomic_load32(&span->heap_id); |
| 1184 | if (heap_id) { |
| 1185 | if (span->size_class < SIZE_CLASS_COUNT) { |
| 1186 | //Small/medium sized block |
| 1187 | size_class_t* size_class = _memory_size_class + span->size_class; |
| 1188 | if ((size_t)size_class->size >= size) |
| 1189 | return p; //Still fits in block, never mind trying to save memory |
| 1190 | if (!oldsize) |
| 1191 | oldsize = size_class->size; |
| 1192 | } |
| 1193 | else { |
| 1194 | //Large block |
| 1195 | size_t total_size = size + SPAN_HEADER_SIZE; |
| 1196 | size_t num_spans = total_size / SPAN_MAX_SIZE; |
| 1197 | if (total_size % SPAN_MAX_SIZE) |
| 1198 | ++num_spans; |
| 1199 | size_t current_spans = (span->size_class - SIZE_CLASS_COUNT) + 1; |
| 1200 | if ((current_spans >= num_spans) && (num_spans >= (current_spans / 2))) |
| 1201 | return p; //Still fits and less than half of memory would be freed |
| 1202 | if (!oldsize) |
| 1203 | oldsize = (current_spans * (size_t)SPAN_MAX_SIZE) - SPAN_HEADER_SIZE; |
| 1204 | } |
| 1205 | } |
| 1206 | else { |
| 1207 | //Oversized block |
| 1208 | size_t total_size = size + SPAN_HEADER_SIZE; |
| 1209 | size_t num_pages = total_size / PAGE_SIZE; |
| 1210 | if (total_size % PAGE_SIZE) |
| 1211 | ++num_pages; |
| 1212 | //Page count is stored in next_span |
| 1213 | size_t current_pages = (size_t)span->next_span; |
| 1214 | if ((current_pages >= num_pages) && (num_pages >= (current_pages / 2))) |
| 1215 | return p; //Still fits and less than half of memory would be freed |
| 1216 | if (!oldsize) |
| 1217 | oldsize = (current_pages * (size_t)PAGE_SIZE) - SPAN_HEADER_SIZE; |
| 1218 | } |
| 1219 | } |
| 1220 | |
| 1221 | //Size is greater than block size, need to allocate a new block and deallocate the old |
| 1222 | //Avoid hysteresis by overallocating if increase is small (below 37%) |
| 1223 | size_t lower_bound = oldsize + (oldsize >> 2) + (oldsize >> 3); |
| 1224 | void* block = _memory_allocate(size > lower_bound ? size : lower_bound); |
| 1225 | if (p) { |
| 1226 | if (!(flags & RPMALLOC_NO_PRESERVE)) |
| 1227 | memcpy(block, p, oldsize < size ? oldsize : size); |
| 1228 | _memory_deallocate(p); |
| 1229 | } |
| 1230 | |
| 1231 | return block; |
| 1232 | } |
| 1233 | |
| 1234 | //! Get the usable size of the given block |
| 1235 | static size_t |
no test coverage detected