/*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- * Title: Simple Memory Manager. * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implementation of a simple memory manager. * ---------------------------------------------------------- */ #include "mem_man.h" #include #include /** * The memory manager operates on a global, statically allocated, linear memory partition (array). * This memory is organized in memory blocks of 32 bits (4 byte), the number of totally * available blocks is defined by the constant 'MEMORY_BLOCK_CNT'. * The smallest allocatable memory unit is one block, larger memory units are allocates always * a multiple of one block. This means, if a memory up to 32 bit is requested, one block is allocated, * if a memory of size from 33 bits to 64 bits is request, two blocks are allocated, and so one. * * Each memory block shall be initialized with the pattern '0xDEADBEEF", freed memory shall be set to * the pattern '0xAFFEBAFF'. Such regions are easily recognizable in a memory dump. * * The housekeeping data (start address and size) of allocated memory units * shall be maintained in a linked list. */ #define MEMORY_BLOCK_CNT 1024 #define BYTES_PER_BLOCK 4 static int memory[MEMORY_BLOCK_CNT]; static size_t allocatedBlocks = 0; static size_t freeBlocks = MEMORY_BLOCK_CNT; static void init_memory() { static int initialized = 0; if (!initialized) { for (size_t i = 0; i < MEMORY_BLOCK_CNT; i++) { memory[i] = 0xAFFEBAFF; } initialized = 1; } } void *my_alloc(size_t size) { init_memory(); if (size == 0) { return (void*)0; } size_t i = 0; size_t start = MEMORY_BLOCK_CNT; size_t freePlaces = 0; size_t blocks_needed = (size + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; while (i < MEMORY_BLOCK_CNT) { if (memory[i] == 0xAFFEBAFF) { if (freePlaces == 0) { start = i; } freePlaces++; if (freePlaces == blocks_needed) { for (size_t j = 0; j < blocks_needed; j++) { memory[start + j] = 0xDEADBEEF; } freeBlocks -= blocks_needed; allocatedBlocks += blocks_needed; return &memory[start]; } } else { freePlaces = 0; start = MEMORY_BLOCK_CNT; } i++; } return NULL; } void my_free(void *p) { int start = get_unit_index(p); if (start == -1) { printf("Memory is not allocated\n"); return; } size_t freed_blocks = 0; size_t i = start; while (i < MEMORY_BLOCK_CNT && memory[i] == 0xDEADBEEF) { memory[i] = 0xAFFEBAFF; freed_blocks++; i++; } freeBlocks += freed_blocks; allocatedBlocks -= freed_blocks; } MemStat mem_get_statistics() { init_memory(); MemStat stat; stat.total_bytes = MEMORY_BLOCK_CNT * BYTES_PER_BLOCK; stat.free_bytes = freeBlocks * BYTES_PER_BLOCK; stat.used_bytes = allocatedBlocks * BYTES_PER_BLOCK; stat.free_percentage = (double)stat.free_bytes / (double)stat.total_bytes * 100; size_t units_count = 0; size_t i = 0; while (i < MEMORY_BLOCK_CNT) { if (memory[i] == 0xDEADBEEF) { units_count++; while (i < MEMORY_BLOCK_CNT && memory[i] == 0xDEADBEEF) { i++; } } else { i++; } } stat.allocated_units_count = units_count; size_t largest_free_unit = 0; size_t current_free_unit = 0; for (i = 0; i < MEMORY_BLOCK_CNT; i++) { if (memory[i] == 0xAFFEBAFF) { current_free_unit++; } else { if (current_free_unit > largest_free_unit) { largest_free_unit = current_free_unit; } current_free_unit = 0; } } if (current_free_unit > largest_free_unit) { largest_free_unit = current_free_unit; } stat.larger_free_unit_bytes = largest_free_unit * BYTES_PER_BLOCK; return stat; } void mem_print_units() { init_memory(); size_t i = 0; while (i < MEMORY_BLOCK_CNT) { if (memory[i] == 0xDEADBEEF) { size_t start = i; size_t size = 0; while (i < MEMORY_BLOCK_CNT && memory[i] == 0xDEADBEEF) { size++; i++; } printf("Allocated: Index %zu; Size: %zu\n", start, size); } else { i++; } } } int get_unit_index(void *p_mem) { if (p_mem < (void*)memory || p_mem >= (void*)(memory + MEMORY_BLOCK_CNT)) { return -1; } int index = ((int*)p_mem - memory); if (memory[index] != 0xDEADBEEF) { return -1; } while (index > 0 && memory[index-1] == 0xDEADBEEF) { index--; } return index; } void mem_dump() { init_memory(); for (size_t i = 0; i < MEMORY_BLOCK_CNT; i++) { printf("Memory: Index %zu; Content 0x%X\n", i, memory[i]); } }