#include #include #include #include #include "_mem.h" // Macro to align a value to a specified alignment. // Ensures that the allocated memory is aligned to a certain boundary (e.g., 16 bytes). #define __mem_align(value, align) ((value + align - 1) & ~(align - 1)) void* malloc(size_t size) { // Handle zero-size allocation. if (size == 0) { return NULL; } // Align the size to 16 bytes. size = __mem_align(size, 16); struct mem_node* current_node = __mem_node; // Start at the head of the linked list. struct mem_node* new_node = NULL; // Pointer to the new node that will be created. // Iterate through the linked list of memory nodes. while (current_node != NULL) { // Check if the current node has enough free space for the requested size. if (size + sizeof(struct mem_node) <= current_node->free) { // Calculate the used memory in current node const size_t s = GET_MEM_NODE_USED_MEM(current_node); // Create a new memory node after the current node's used space. new_node = (struct mem_node*)(GET_MEM_NODE_PTR(current_node) + s); // Set the size of the new node. new_node->size = current_node->free - sizeof(struct mem_node); // Update current node's size current_node->size = s; // Mark current node as used. current_node->free = 0; break; // Found a suitable node, exit the loop. } current_node = current_node->next; // Move to the next node in the list. } // If no suitable node was found in the existing list: if (new_node == NULL) { // Calculate the size of the new block, including the mem_block header, mem_node header and alignment. const size_t s = __mem_align(size + sizeof(struct mem_block) + sizeof(struct mem_node), ALLOC_BLOCK_SIZE); // Allocate a new block of memory using the ksys_alloc function (presumably a kernel-level allocation function). struct mem_block* block = (struct mem_block*)_ksys_alloc(s); // Check if the allocation was successful. if (block == NULL) { __errno = ENOMEM; // Set the error number to indicate memory allocation failure. return NULL; // Return NULL to indicate allocation failure. } // Create a new memory node after the mem_block header. new_node = (struct mem_node*)(block + sizeof(struct mem_block)); // Set the size of the new node. new_node->size = s - sizeof(struct mem_block) - sizeof(struct mem_node); } // Set the free space in the new node. new_node->free = new_node->size - size; // Set the last pointer of the new node to the current node. new_node->last = current_node; // Link the new node into the linked list. if (current_node != NULL) { // Set the next pointer of the current node to the new node. new_node->next = current_node->next; // Update the last pointer of the next node, if it exists. if (current_node->next != NULL) { current_node->next->last = new_node; } current_node->next = new_node; } else { // If the current node is NULL, the new node is the first node in the list. new_node->next = NULL; } // If the linked list was empty, set the head to the new node. if (__mem_node == NULL) { __mem_node = new_node; } // Return a pointer to the user data area of the new node. return GET_MEM_NODE_PTR(new_node); } #undef __mem_align