libc.obj: update malloc/free/realloc
гавно говна, нужно доработать
This commit is contained in:
53
programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h
Normal file
53
programs/develop/ktcc/trunk/libc.obj/source/stdlib/_mem.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef _LIBC_STDLIB__MEM_
|
||||||
|
#define _LIBC_STDLIB__MEM_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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_
|
||||||
@@ -1,7 +1,74 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <sys/ksys.h>
|
#include <sys/ksys.h>
|
||||||
|
#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)
|
void free(void* ptr)
|
||||||
{
|
{
|
||||||
_ksys_free(ptr);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,72 @@
|
|||||||
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/ksys.h>
|
#include <sys/ksys.h>
|
||||||
|
#include "_mem.h"
|
||||||
|
|
||||||
void* malloc(size_t size)
|
void* malloc(size_t size)
|
||||||
{
|
{
|
||||||
return _ksys_alloc(size);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/ksys.h>
|
#include <sys/ksys.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "_mem.h"
|
||||||
|
|
||||||
void* realloc(void* ptr, size_t newsize)
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user