Files
kolibrios/programs/develop/ktcc/trunk/libc.obj/source/stdlib/realloc.c
Egor00f cb29ecffb7
All checks were successful
Build system / Check kernel codestyle (pull_request) Successful in 41s
Build system / Build (pull_request) Successful in 16m37s
libc.obj: fixes and optimizations for allocator && add new samples to sh build
fix: in `__mem_MERGE_MEM_NODES` `base->free = base->size`, its wrong.
forgot to set size for new block
optimization: add `__last_mem_node`. usually  its node with max free space among other nodes. firstly `malloc` try find space in it.
update(fix and optimizations) `realloc`.
now sdltest is working!
2026-02-04 12:42:00 +05:00

65 lines
2.3 KiB
C

#include <stdlib.h>
#include <string.h>
#include <sys/ksys.h>
#include "_mem.h"
// realloc mem. using if other ways not working
void* fail_realloc(void* ptr, size_t newsize)
{
// Allocate a new block of memory with the new size.
void* new_ptr = malloc(newsize);
// If both the old pointer and the new pointer are not NULL:
if (ptr != NULL && new_ptr != NULL) {
// Copy the data from the old block to the new block.
memcpy(new_ptr, ptr, min(newsize, GET_MEM_NODE_USED_MEM(GET_MEM_NODE_HEADER(ptr))));
}
if (ptr) {
free(ptr); // Free the old block.
}
return new_ptr;
}
void* realloc(void* ptr, size_t newsize)
{
void* new_ptr = NULL;
struct mem_node* node = NULL;
if (ptr && newsize) {
// Get a pointer to the mem_node header from the user data pointer.
node = GET_MEM_NODE_HEADER(ptr);
if (node->size >= newsize) { // current node have enough mem
// it work always if newsize is smaller
// Update the free space in the current node.
node->free = node->size - newsize;
// Return the original pointer.
new_ptr = ptr;
} else if (node->next && MEM_NODE_IS_FREE(node->next) && node->size + node->next->size >= newsize) {
// So what happens here is that the node merges with the next node if their volume is sufficient.
// And a reallock is called in the hopes that the first condition will be met.
// if merge failed realloc anyway return pointer, but it will got from `fail_realloc`
// it faster than merge with last node, because its not make a copy/move
new_ptr = realloc(GET_MEM_NODE_PTR(__mem_MERGE_MEM_NODES(node, node->next)), newsize);
} else if (node->last && MEM_NODE_IS_FREE(node->last) && node->size + node->last->size >= newsize) {
struct mem_node* l = node->last;
l = __mem_MERGE_MEM_NODES(l, node);
if (l)
memmove(GET_MEM_NODE_PTR(l), ptr, GET_MEM_NODE_USED_MEM(node));
new_ptr = realloc(GET_MEM_NODE_PTR(l), newsize);
} else {
new_ptr = fail_realloc(ptr, newsize);
}
} else {
new_ptr = fail_realloc(ptr, newsize);
}
// Return the new pointer.
return new_ptr;
}