Files
kolibrios/programs/develop/ktcc/trunk/libc.obj/source/stdlib/malloc.c

79 lines
2.6 KiB
C

#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ksys.h>
#include "_mem.h"
#define __mem_align(value, align) ((value + align - 1) & ~(align - 1))
void* malloc(size_t 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) {
__errno = ENOMEM;
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);
}
#undef __mem_align