October 22, 2024
Chicago 12, Melborne City, USA
C#

How can cli still work when memory manager doesnt give it memory? Custom OS x86_64


Developing a memory manager and for some reason cli works normally even when memory manager doesnt give it memory? When memory manager is initialised cli retrieves a bit of memory from it and Memory Manager correctly recongises it as allocated memory.

Is there any explanation for this or is it a issue?

Adding Memory Manager below.

#include "memory.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "snprintf.h"
#include "vga.h"

extern char __memory_pool_start;
extern char __memory_pool_end;

#define ALIGNMENT 8
#define ALIGN_MASK (ALIGNMENT - 1)

#define ERR_NO_MEMORY 1
#define KMALLOC_FLAG_RESERVED 0x1

typedef struct MemoryBlock {
    size_t size;
    bool is_free;
    struct MemoryBlock* next;
    struct MemoryBlock* prev;
} MemoryBlock;

static char* memory_pool_start;
static size_t memory_pool_size;
static MemoryBlock* free_list = NULL;
static MemoryBlock* allocated_list = NULL;
static MemoryBlock* reserved_free_list = NULL;
static MemoryBlock* reserved_allocated_list = NULL;

static int last_error;

static size_t align_size(size_t size) {
    return (size + ALIGN_MASK) & ~ALIGN_MASK;
}

void initialize_memory_manager() {
    memory_pool_start = &__memory_pool_start;
    memory_pool_size = &__memory_pool_end - &__memory_pool_start;

    size_t reserved_size = memory_pool_size / 4;
    size_t general_size = memory_pool_size - reserved_size;

    // Initialize general pool
    free_list = (MemoryBlock*)memory_pool_start;
    free_list->size = general_size - sizeof(MemoryBlock);
    free_list->is_free = true;
    free_list->next = NULL;
    free_list->prev = NULL;

    // Initialize reserved pool
    reserved_free_list = (MemoryBlock*)(memory_pool_start + general_size);
    reserved_free_list->size = reserved_size - sizeof(MemoryBlock);
    reserved_free_list->is_free = true;
    reserved_free_list->next = NULL;
    reserved_free_list->prev = NULL;
}

static void split_block(MemoryBlock* block, size_t size) {
    if (block->size >= size + sizeof(MemoryBlock) + ALIGNMENT) {
        MemoryBlock* new_block = (MemoryBlock*)((char*)block + sizeof(MemoryBlock) + size);
        new_block->size = block->size - size - sizeof(MemoryBlock);
        new_block->is_free = true;
        new_block->next = block->next;
        new_block->prev = block;
        if (block->next) {
            block->next->prev = new_block;
        }
        block->next = new_block;
        block->size = size;
    }
}

static void coalesce_blocks(MemoryBlock* block) {
    if (block->next && block->next->is_free) {
        block->size += sizeof(MemoryBlock) + block->next->size;
        block->next = block->next->next;
        if (block->next) {
            block->next->prev = block;
        }
    }
    if (block->prev && block->prev->is_free) {
        block->prev->size += sizeof(MemoryBlock) + block->size;
        block->prev->next = block->next;
        if (block->next) {
            block->next->prev = block->prev;
        }
    }
}

void defragment_memory() {
    MemoryBlock* current = free_list;
    while (current && current->next) {
        if (current->is_free && current->next->is_free) {
            coalesce_blocks(current);
        } else {
            current = current->next;
        }
    }

    current = reserved_free_list;
    while (current && current->next) {
        if (current->is_free && current->next->is_free) {
            coalesce_blocks(current);
        } else {
            current = current->next;
        }
    }
}

void* kmalloc(size_t size, int flags) {
    size = align_size(size);
    MemoryBlock* current = (flags & KMALLOC_FLAG_RESERVED) ? reserved_free_list : free_list;

    // Debugging output
    char buffer[256];
    snprintf(buffer, sizeof(buffer), "Requesting %zu bytes from kmalloc\n", size);
    print_str(buffer);

    while (current) {
        if (current->is_free && current->size >= size) {
            split_block(current, size);
            current->is_free = false;

            // Remove from free list
            if (current->prev) {
                current->prev->next = current->next;
            } else {
                if (flags & KMALLOC_FLAG_RESERVED) {
                    reserved_free_list = current->next;
                } else {
                    free_list = current->next;
                }
            }
            if (current->next) {
                current->next->prev = current->prev;
            }

            // Add to allocated list
            current->next = (flags & KMALLOC_FLAG_RESERVED) ? reserved_allocated_list : allocated_list;
            if (flags & KMALLOC_FLAG_RESERVED) {
                if (reserved_allocated_list) {
                    reserved_allocated_list->prev = current;
                }
                reserved_allocated_list = current;
            } else {
                if (allocated_list) {
                    allocated_list->prev = current;
                }
                allocated_list = current;
            }

            // Debugging output
            snprintf(buffer, sizeof(buffer), "Allocated %zu bytes at %p\n", size, (void*)((char*)current + sizeof(MemoryBlock)));
            print_str(buffer);

            return (void*)((char*)current + sizeof(MemoryBlock));
        }
        current = current->next;
    }

    last_error = ERR_NO_MEMORY;
    print_str("kmalloc failed: Out of memory\n");
    return NULL;
}

void kfree(void* ptr) {
    if (!ptr) return;
    MemoryBlock* block = (MemoryBlock*)((char*)ptr - sizeof(MemoryBlock));
    block->is_free = true;

    // Remove from allocated list
    if (block->prev) {
        block->prev->next = block->next;
    } else {
        if (block >= (MemoryBlock*)memory_pool_start && block < (MemoryBlock*)(memory_pool_start + memory_pool_size / 4 * 3)) {
            allocated_list = block->next;
        } else {
            reserved_allocated_list = block->next;
        }
    }
    if (block->next) {
        block->next->prev = block->prev;
    }

    coalesce_blocks(block);
}

const char* get_error_message(int error_code) {
    switch (error_code) {
        case ERR_NO_MEMORY:
            return "Out of memory";
        default:
            return "Unknown error";
    }
}

void check_memory_leaks() {
    if (allocated_list || reserved_allocated_list) {
        print_str("Memory Leak Warning: The following blocks were not freed:\n");
        MemoryBlock* current = allocated_list;
        while (current) {
            char buffer[256];
            snprintf(buffer, sizeof(buffer), "Leaked Block: Size = %zu bytes\n", current->size);
            print_str(buffer);
            current = current->next;
        }
        current = reserved_allocated_list;
        while (current) {
            char buffer[256];
            snprintf(buffer, sizeof(buffer), "Leaked Block: Size = %zu bytes\n", current->size);
            print_str(buffer);
            current = current->next;
        }
    } else {
        print_str("No memory leaks detected.\n");
    }
}

void print_memory_stats() {
    size_t total_memory = memory_pool_size;
    size_t used_memory = 0;
    size_t free_memory = 0;
    size_t reserved_free_memory = 0;

    MemoryBlock* current = free_list;
    while (current) {
        if (current->is_free) {
            free_memory += current->size + sizeof(MemoryBlock);
        }
        current = current->next;
    }

    current = allocated_list;
    while (current) {
        if (!current->is_free) {
            used_memory += current->size + sizeof(MemoryBlock);
        }
        current = current->next;
    }

    current = reserved_free_list;
    while (current) {
        if (current->is_free) {
            reserved_free_memory += current->size + sizeof(MemoryBlock);
        }
        current = current->next;
    }

    current = reserved_allocated_list;
    while (current) {
        if (!current->is_free) {
            used_memory += current->size + sizeof(MemoryBlock);
        }
        current = current->next;
    }

    char buffer[256];
    snprintf(buffer, sizeof(buffer), "Total Memory: %zu bytes\n", total_memory);
    print_str(buffer);
    snprintf(buffer, sizeof(buffer), "Used Memory: %zu bytes\n", used_memory);
    print_str(buffer);
    snprintf(buffer, sizeof(buffer), "Free Memory: %zu bytes\n", free_memory);
    print_str(buffer);
    snprintf(buffer, sizeof(buffer), "Reserved Free Memory: %zu bytes\n", reserved_free_memory);
    print_str(buffer);
}

__attribute__((constructor))
static void setup_memory() {
    initialize_memory_manager();
}

__attribute__((destructor))
static void cleanup_memory() {
    check_memory_leaks();
}

And the part of cli.

#define MAX_COMMAND_LENGTH 256 // Requested memory
char *command_buffer = NULL; 

void init_cli() {
    command_buffer = (char *)kmalloc(MAX_COMMAND_LENGTH, 0); // Allocate memory for command_buffer
    if (command_buffer == NULL) {
        print_set_color(PRINT_COLOR_RED, PRINT_COLOR_BLACK);
        print_str("Failed to allocate memory for command buffer\n");
        return;
    }
    set_cursor_position(CLI_PROMPT_LENGTH); 
    print_clear(); 
    print_prompt(); 
}

Added some debug prints and everything seems to be correct.But for some reason location of the allocated memory isnt printed.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video