libc.obj: some small changes
кусок кода в `realloc`, провереющий на свободную ноду безсмысленен, т.к. в `free` в любом случае сливает освобождаемую ноду с предыдущей.
This commit is contained in:
@@ -15,9 +15,12 @@ struct mem_node {
|
||||
struct mem_block {
|
||||
size_t size; // Size of the allocated memory block.
|
||||
|
||||
size_t a; // align to 8bytes
|
||||
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))
|
||||
@@ -30,18 +33,24 @@ struct mem_block {
|
||||
|
||||
// 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)))
|
||||
#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)
|
||||
|
||||
// Size of the blocks allocated by `_ksys_alloc`
|
||||
#define ALLOC_BLOCK_SIZE 4096
|
||||
|
||||
// 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
|
||||
|
||||
@@ -36,7 +36,7 @@ void free(void* ptr)
|
||||
// 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))) {
|
||||
&& (node->next == 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));
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
#include <stdbool.h>
|
||||
#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))
|
||||
|
||||
static struct mem_node* __new_mem_node_from_exist(struct mem_node* current_node, size_t size, bool* from_empty_node)
|
||||
{
|
||||
struct mem_node* new_node = NULL;
|
||||
@@ -49,9 +45,9 @@ void* malloc(size_t size)
|
||||
}
|
||||
|
||||
// Align the size to 8 bytes.
|
||||
size = __mem_align(size, 8);
|
||||
size = __mem_default_align(size);
|
||||
|
||||
struct mem_node* current_node = NULL;
|
||||
struct mem_node* current_node = __mem_node;
|
||||
struct mem_node* new_node = NULL; // Pointer to the new node that will be created.
|
||||
bool from_empty_node = false;
|
||||
|
||||
@@ -60,8 +56,6 @@ void* malloc(size_t size)
|
||||
|
||||
// if cant find in __last_biggest_mem_node
|
||||
if (new_node == NULL) {
|
||||
current_node = __mem_node; // Start at the head of the linked list.
|
||||
|
||||
// Iterate through the linked list of memory nodes.
|
||||
while (current_node != NULL) {
|
||||
new_node = __new_mem_node_from_exist(current_node, size, &from_empty_node);
|
||||
@@ -89,7 +83,7 @@ void* malloc(size_t size)
|
||||
block->size = s;
|
||||
|
||||
// Create a new memory node after the mem_block header.
|
||||
new_node = (struct mem_node*)(block + sizeof(struct mem_block));
|
||||
new_node = (struct mem_node*)(((char*)block) + sizeof(struct mem_block));
|
||||
|
||||
// Set the size of the new node.
|
||||
new_node->size = s - sizeof(struct mem_block) - sizeof(struct mem_node);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "_mem.h"
|
||||
|
||||
// realloc mem. using if other ways not working
|
||||
void* fail_realloc(void* ptr, size_t newsize)
|
||||
static void* fail_realloc(void* ptr, size_t newsize)
|
||||
{
|
||||
// Allocate a new block of memory with the new size.
|
||||
void* new_ptr = malloc(newsize);
|
||||
@@ -16,7 +16,7 @@ void* fail_realloc(void* ptr, size_t newsize)
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
free(ptr); // Free the old block.
|
||||
free(ptr); // Free the old block.
|
||||
}
|
||||
|
||||
return new_ptr;
|
||||
@@ -33,32 +33,44 @@ void* realloc(void* ptr, size_t newsize)
|
||||
// Get a pointer to the mem_node header from the user data pointer.
|
||||
node = GET_MEM_NODE_HEADER(ptr);
|
||||
|
||||
newsize = __mem_default_align(newsize);
|
||||
|
||||
if (node->size >= newsize) { // current node have enough mem
|
||||
// it work always if newsize is smaller
|
||||
// Update the free space in the current node.
|
||||
node->free = node->size - newsize;
|
||||
// Return the original pointer.
|
||||
new_ptr = ptr;
|
||||
} else if (node->next && MEM_NODE_IS_FREE(node->next) && node->size + node->next->size >= newsize) {
|
||||
// So what happens here is that the node merges with the next node if their volume is sufficient.
|
||||
} else if (node->last && MEM_NODE_IS_FREE(node->last) && node->size + node->last->size >= newsize) {
|
||||
// So what happens here is that the node merges with the last node if their volume is sufficient.
|
||||
// And a reallock is called in the hopes that the first condition will be met.
|
||||
// if merge failed realloc anyway return pointer, but it will got from `fail_realloc`
|
||||
// it faster than merge with last node, because its not make a copy/move
|
||||
new_ptr = realloc(GET_MEM_NODE_PTR(__mem_MERGE_MEM_NODES(node, node->next)), newsize);
|
||||
} else if (node->last && MEM_NODE_IS_FREE(node->last) && node->size + node->last->size >= newsize) {
|
||||
struct mem_node* l = node->last;
|
||||
|
||||
l = __mem_MERGE_MEM_NODES(l, node);
|
||||
if (l)
|
||||
if (l) {
|
||||
memmove(GET_MEM_NODE_PTR(l), ptr, GET_MEM_NODE_USED_MEM(node));
|
||||
new_ptr = realloc(GET_MEM_NODE_PTR(l), newsize);
|
||||
} else {
|
||||
new_ptr = fail_realloc(ptr, newsize);
|
||||
new_ptr = realloc(GET_MEM_NODE_PTR(l), newsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_ptr == NULL) {
|
||||
|
||||
// Allocate a new block of memory with the new size.
|
||||
new_ptr = malloc(newsize);
|
||||
|
||||
// If both the old pointer and the new pointer are not NULL:
|
||||
if (ptr != NULL && new_ptr != NULL) {
|
||||
// Copy the data from the old block to the new block.
|
||||
memcpy(new_ptr, ptr, min(newsize, GET_MEM_NODE_USED_MEM(GET_MEM_NODE_HEADER(ptr))));
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
free(ptr); // Free the old block.
|
||||
}
|
||||
} else {
|
||||
new_ptr = fail_realloc(ptr, newsize);
|
||||
}
|
||||
|
||||
// Return the new pointer.
|
||||
return new_ptr;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user