forked from KolibriOS/kolibrios
75 lines
3.2 KiB
C
75 lines
3.2 KiB
C
#include <stdlib.h>
|
||
#include <stdbool.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)
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
}
|