diff --git a/mem_man.c b/mem_man.c index f158418..4ceb1b5 100644 --- a/mem_man.c +++ b/mem_man.c @@ -28,68 +28,166 @@ * shall be maintained in a linked list. */ -#define MEMORY_BLOCK_CNT 1024; +#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; -/** - * Allocates a memory block of the given size in bytes - * in a similar way as `malloc(size)`. - * - * @param size The number of bytes to allocate. - * @return The pointer to the allocated memory block or 0, - * if no memory could be allocated. - */ -void* my_alloc(size_t size) { - return 0; +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; + } } -/** - * Releases the addressed memory block that was allocated via function `my_alloc(...)`. - * If the addressed memory is not allocated, a warning is printed. - * - * @param p The pointer to the memory to free. - */ -void my_free(void* p) { - return; +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; } -/** - * Prints a brief statistic report about memory that reveals the following key values: - * # total available memory in bytes. - * # free (not allocated) memory in bytes. - * # used (allocated) memory in bytes - * # free memory in percentage (0 % to 100%) - * # number of allocated units (continuously allocated portions of the memory, not memory blocks) - * # largest free continuous memory unit in bytes. - */ MemStat mem_get_statistics() { - return (MemStat){0, 0, 0, 0, 0, 0}; + 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; } -/** - * Prints the allocated units (continuously allocated portions of the memory, not memory blocks) - * including their start address within the managed memory as well as their size - * ordered by their start address. - */ void mem_print_units() { - return; + 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++; + } + } } -/** - * Provides the index of the allocated unit (continuously allocated portions of the memory, not memory blocks) - * the addressed memory belongs to. If the addressed memory is not allocated or the address is outside - * the range of the managed memory, a value less than zero provided. - * - * @param p_mem The pointer to the memory to query. - * @return The unit index the address belongs to or a value less than 0 if the memory is not allocated. - */ -int get_unit_index(void* p_mem) { - return 0; +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; } -/** - * Dumps the content of the memory. - */ void mem_dump() { - return; -} \ No newline at end of file + init_memory(); + + for (size_t i = 0; i < MEMORY_BLOCK_CNT; i++) { + printf("Memory: Index %zu; Content 0x%X\n", i, memory[i]); + } +}