#include #include #include #include "_mem.h" void free(void* ptr) { // Handle NULL pointer. if (ptr == NULL) return; // Get a pointer to the mem_node header from the user data pointer. struct mem_node* node = GET_MEM_NODE_HEADER(ptr); // Mark the memory node as free. node->free = node->size; if (__last_biggest_mem_node == node) { if (node->last) { __last_biggest_mem_node = node->last; // anyway node will be merged with next // and last and last will have size = last + node + next(if its free too) } } // Merge with the next node if possible. if (node->next != NULL) __mem_MERGE_MEM_NODES(node, node->next); // Merge with the previous node if possible. if (node->last != NULL) node = __mem_MERGE_MEM_NODES(node->last, node); if (node) { // If the current node is not adjacent to either the next or previous node, // it might be a separate block that can be freed. if (MEM_NODE_IS_FREE(node) // check it because node maybe was merged with last && (node->last == NULL || !MEM_NODES_ARE_IN_ONE_BLOCK(node, node->next)) && (node->last == NULL || !MEM_NODES_ARE_IN_ONE_BLOCK(node->last, node))) { // Get a pointer to the mem_block header from the mem_node header. struct mem_block* block = (struct mem_block*)(((char*)node) - sizeof(struct mem_block)); // Check if the block size matches the node size. if (block->size == node->size + sizeof(struct mem_block) + sizeof(struct mem_node)) { // Update the linked list pointers to remove the current node. if (node->last != NULL) node->last->next = node->next; if (node->next != NULL) node->next->last = node->last; // Update the head of the linked list if necessary. 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; } } struct mem_node* a = node->next; struct mem_node* b = node->last; if (!a && !b) { __last_biggest_mem_node = NULL; } else if (a && !b) { __last_biggest_mem_node = a; } else if (!a && b) { __last_biggest_mem_node = b; } else if (a && b) { __last_biggest_mem_node = (a->free > b->free) ? a : b; } if (__last_biggest_mem_node == node) { if (node->next && !(node->last)) { __last_biggest_mem_node = node->next; } else if (node->last && !(node->next)) { __last_biggest_mem_node = node->last; } else if (node->next && node->last) { if (node->last->free > node->next->free) { __last_biggest_mem_node = node->last; } else { __last_biggest_mem_node = node->next; } } } // Free the memory block using the ksys_free function. _ksys_free(block); } } } }