#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) { 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); } } }