#ifndef _LIBC_STDLIB__MEM_ #define _LIBC_STDLIB__MEM_ #include struct mem_node { size_t free; // Amount of free space in this node. When equal to size, the entire node is free. size_t size; // Total size of this memory node. struct mem_node* last; // Pointer to the previous memory node in the linked list. struct mem_node* next; // Pointer to the next memory node in the linked list. }; struct mem_block { size_t size; // Size of the allocated memory block. size_t a; // align to 8bytes }; // Size of the blocks allocated by `_ksys_alloc` #define ALLOC_BLOCK_SIZE 4096 // Macro to get a pointer to the user data area from a mem_node pointer. // This is done by adding the size of the mem_node structure to the mem_node pointer. #define GET_MEM_NODE_PTR(node) (char*)((char*)(node) + sizeof(struct mem_node)) // Macro to check if a memory node is completely free. #define MEM_NODE_IS_FREE(node) (node->free == node->size) // Macro to get the amount of used memory in a memory node. #define GET_MEM_NODE_USED_MEM(node) (node->size - node->free) // Macro to get a pointer to the mem_node structure from a user data pointer. // This is done by subtracting the size of the mem_node structure from the user data pointer. #define GET_MEM_NODE_HEADER(ptr) ((struct mem_node*)(((char*)ptr) - sizeof(struct mem_node))) // Macro to check if two adjacent memory nodes are in the same block. // Checks if the end of the left node's allocated space is the start of the right node. #define MEM_NODES_ARE_IN_ONE_BLOCK(left, right) (GET_MEM_NODE_PTR(left) + ((struct mem_node*)left)->size == (char*)right) // Macro to merge two adjacent memory nodes. #define CHECK_SIDE_IN_OTHER_BLOCK(node, side) (side == NULL || ((side != NULL) && !MEM_NODES_ARE_IN_ONE_BLOCK(node, side))) // align a value to a specified alignment. // Ensures that the allocated memory is aligned to a certain boundary inline size_t __mem_align(size_t value, size_t align) { return ((value + align - 1) & ~(align - 1)); } #define __mem_default_align(value) __mem_align(value, 8) inline struct mem_node* __mem_MERGE_MEM_NODES(struct mem_node* base, struct mem_node* addition) { // addition is free && nodes base and addition both in one block, else merge is impossible if (MEM_NODE_IS_FREE(addition) && MEM_NODES_ARE_IN_ONE_BLOCK(base, addition)) { // just change size const size_t s = addition->size + sizeof(struct mem_node); base->size += s; base->free += s; // and delete addition from list if (addition->next != NULL) { addition->next->last = base; base->next = addition->next; } else { base->next = NULL; } return base; } return NULL; } // Static pointer to the first memory node in the linked list. // This acts as the head of the memory pool. static struct mem_node* __mem_node = NULL; static struct mem_node* __last_biggest_mem_node = NULL; #endif // _LIBC_STDLIB_MEM_