79 lines
2.6 KiB
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
|