From bb59eac8d6d53567cb5ccea9e4fbdfb29b915044 Mon Sep 17 00:00:00 2001 From: Egor00f Date: Wed, 14 Jan 2026 00:03:55 +0500 Subject: [PATCH] libc.obj: update malloc/free/realloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit гавно говна, нужно доработать --- .../ktcc/trunk/libc.obj/source/stdlib/_mem.h | 53 ++++++++++++++ .../ktcc/trunk/libc.obj/source/stdlib/free.c | 71 ++++++++++++++++++- .../trunk/libc.obj/source/stdlib/malloc.c | 69 +++++++++++++++++- .../trunk/libc.obj/source/stdlib/realloc.c | 12 +++- 4 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h new file mode 100644 index 000000000..04f159cab --- /dev/null +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h @@ -0,0 +1,53 @@ +#ifndef _LIBC_STDLIB__MEM_ +#define _LIBC_STDLIB__MEM_ + +#include + +struct mem_node { + // сколько свободно + size_t free; + + // Размер блока + size_t size; + + struct mem_node* last; + struct mem_node* next; + + // реально выделена под него память + // если нет, то он получается был втиснут в другой блок + // bool is_real; +}; + +// блок выделенной памяти +struct mem_block { + size_t size; // сколько было полученно памяти +}; + +// получить указатель на данные ноды +#define GET_MEM_NODE_PTR(node) (char*)((char*)(node) + sizeof(struct mem_node)) + +// Является ли блок сейчас пустым +#define MEM_NODE_IS_FREE(node) (node->free == node->size) + +#define GET_mem_node_USED_MEM(node) (node->size - node->free) + +#define GET_mem_node_HEADER(ptr) ((struct mem_node*)((char*)ptr - sizeof(struct mem_node))) + +// проверить находятся ли ноды в одном блоке. +// Если они в одном блоке, но получаестя они должны идти друг за другом +#define mem_nodeS_ARE_IN_ONE_BLOCK(left, right) (GET_MEM_NODE_PTR(left) + left->size == (char*)right) + + +// Размер блока +#define ALLOC_BLOCK_SIZE 4096 + +inline size_t __mem_align(size_t value, size_t v) +{ + size_t ret = (value + v - 1) & ~(v - 1); + + return ret; +} + +static struct mem_node* __mem_node = NULL; + +#endif // _LIBC_STDLIB_MEM_ diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/free.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/free.c index afce966cc..bf5e341a5 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/free.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/free.c @@ -1,7 +1,74 @@ #include +#include #include +#include "_mem.h" + +// Объеденить два блока (срабоает только для блоков в одном куске памяти) +// добавление обязательно должно быть справа +inline void __mem_MERGE_MEM_NODES(struct mem_node* base, struct mem_node* addition) +{ // проверка что они оба не NULL Проверка, что base находится слева от addition проверка, что они оба свободные + if (MEM_NODE_IS_FREE(addition) && mem_nodeS_ARE_IN_ONE_BLOCK(base, addition)) { + // просто тупо увеличиается размер ибо пофиг на данные что там были + const size_t s = addition->size + sizeof(struct mem_node); + base->size += s; + base->free = base->size; + + if (addition->next != NULL) { + addition->next->last = base; + base->next = addition->next; + } else { + base->next = NULL; + } + } +} + +#define CHECK_SIDE_IN_OTHER_BLOCK(node, side) (side == NULL || ((side != NULL) && !mem_nodeS_ARE_IN_ONE_BLOCK(, node))) void free(void* ptr) { - _ksys_free(ptr); -} \ No newline at end of file + if (ptr == NULL) + return; + + struct mem_node* node = GET_mem_node_HEADER(ptr); + + // падает сдесь + node->free = node->size; // помечен как свободный + + // и сливается с соседними блоками + + if (node->next != NULL) + __mem_MERGE_MEM_NODES(node, node->next); + if (node->last != NULL) + __mem_MERGE_MEM_NODES(node->last, node); + + // если нода единственная в блоке, т.к. соседние ноды находятся в других нодах или отсутвуют + if ((node->next == NULL || ((node->next != NULL) && !mem_nodeS_ARE_IN_ONE_BLOCK(node, node->next))) + && (node->last == NULL || ((node->last != NULL) && !mem_nodeS_ARE_IN_ONE_BLOCK(node->last, node)))) { + struct mem_block* block = (struct mem_block*)(((char*)node) - sizeof(struct mem_block)); + + // размер блока совпадает с размером ноды (т.е. проверка, что нода ТОЧНО одна в блоке) + // если размер ноды меньше, то значит где-то в переди есть занятые ноды, + // когда они освободятся то блок освободится + if (block->size == node->size + sizeof(struct mem_block) + sizeof(struct mem_node)) { + + // востановление списка + if (node->last != NULL) + node->last->next = node->next; + + if (node->next != NULL) + node->next->last = node->last; + + if (__mem_node == node) { + if (node->last != NULL) { + __mem_node = node->last; + } else if (node->next != NULL) { + __mem_node = node->next; + } else { + __mem_node = NULL; + } + } + _ksys_debug_puts("free block"); + _ksys_free(block); + } + } +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/malloc.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/malloc.c index c96d5a521..6954c7697 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/malloc.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/malloc.c @@ -1,7 +1,72 @@ +#include #include #include +#include "_mem.h" void* malloc(size_t size) { - return _ksys_alloc(size); -} \ No newline at end of file + if (size == 0) + return NULL; + + struct mem_node* current_node = __mem_node; + struct mem_node* new_node = NULL; + + size = __mem_align(size, 16); // выравнивание + + // поиск ноды в которой есть достаточно всободного места + while (current_node != NULL) { // зависает на поиске + if (size + sizeof(struct mem_node) <= current_node->free) { + + const size_t s = GET_mem_node_USED_MEM(current_node); + + new_node = (struct mem_node*)(GET_MEM_NODE_PTR(current_node) + s); + new_node->size = current_node->free - sizeof(struct mem_node); + + current_node->size = s; // т.к. новая нода идёт сразу после занятых данных + current_node->free = 0; // поэтому под новую ноду выдлятся всё доступное пространство + + break; + } + current_node = current_node->next; + } + + if (new_node == NULL) // ну не получилось найти подходящий блок, в который удалось втиснуть + { + const size_t s = __mem_align(size + sizeof(struct mem_block) + sizeof(struct mem_node), ALLOC_BLOCK_SIZE); + + // заголовок блока в начале памяти, после идёт нода + struct mem_block* block = (struct mem_block*)_ksys_alloc(s); + + if (block == NULL) { + + return NULL; + } + + // нода идёт сразу после заглоловка блока + new_node = (struct mem_node*)(block + sizeof(struct mem_block)); + + // и под ноду выделяется всё доступное место блока + new_node->size = s - sizeof(struct mem_block) - sizeof(struct mem_node); + } + + new_node->free = new_node->size - size; // сразу выделяется под используемые данные + + new_node->last = current_node; + + if (current_node != NULL) { + new_node->next = current_node->next; + + if (current_node->next != NULL) { + current_node->next->last = new_node; + } + current_node->next = new_node; + } else { + new_node->next = NULL; + } + + if (__mem_node == NULL) { + __mem_node = new_node; + } + + return GET_MEM_NODE_PTR(new_node); +} diff --git a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/realloc.c b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/realloc.c index 6278a9199..c7ab21822 100644 --- a/programs/develop/ktcc/trunk/libc.obj/source/stdlib/realloc.c +++ b/programs/develop/ktcc/trunk/libc.obj/source/stdlib/realloc.c @@ -1,7 +1,17 @@ #include #include +#include +#include "_mem.h" void* realloc(void* ptr, size_t newsize) { - return _ksys_realloc(ptr, newsize); + void *new_ptr = malloc(newsize); + + if(ptr != NULL && new_ptr != NULL) + { + memcpy(new_ptr, ptr, min(newsize, GET_mem_node_HEADER(ptr)->size)); + free(ptr); + } + + return new_ptr; } \ No newline at end of file