Aprelius logo
uptime: 00:00:00

source file

memory_allocator.c

Full source referenced by a note. Click a line number to copy its URL.

memory_allocator.cc
1#include <stddef.h>2#include <stdio.h>3#include <stdlib.h>4#include <sys/mman.h>5 6#define ARENA_SIZE (1024 * 1024)7 8typedef struct {9  char *start;10  char *end;11  char *cursor;12} Arena;13 14typedef struct {15  size_t size;16  int is_free;17} Header;18 19static inline size_t block_span(size_t size) { return sizeof(Header) + size; }20 21Arena g_arena;22 23void arena_coalescing(Header *header) {24  char *next_addr = (char *)header + block_span(header->size);25  if (next_addr >= g_arena.cursor)26    return;27  Header *next_header = (Header *)next_addr;28  if (next_header->is_free) {29    header->size += block_span(next_header->size);30  }31}32 33// process_header split header if needed, then set is_free flag properly34void process_header(Header *header, size_t size, char *head_addr) {35  if (header->size > block_span(size)) {36    char *new_addr = head_addr + block_span(size);37    Header h = {header->size - size - sizeof(Header), 1};38    *(Header *)new_addr = h;39    header->size = size;40  }41  header->is_free = 0;42}43 44// find_free_block - iterate over headers, check for the one that can fit45// requested size46void *find_free_block(size_t size) {47  char *current = g_arena.start;48  while (current < g_arena.cursor) {49    Header *header = (Header *)current;50    if (header->is_free) {51      if (header->size >= size) {52        process_header(header, size, current);53        return current + sizeof(*header);54      } else {55      }56    }57    current += block_span(header->size);58  }59  return NULL;60}61 62void *arena_alloc(size_t size) {63  void *alloc = find_free_block(size);64  if (alloc != NULL) {65    return alloc;66  }67 68  if (g_arena.end - g_arena.cursor >= block_span(size)) {69    Header h = {size, 0};70    Header *h_addr = (Header *)g_arena.cursor;71    *h_addr = h;72    g_arena.cursor += sizeof(h);73    char *user_mem = g_arena.cursor;74    g_arena.cursor += size;75    return user_mem;76  }77  return NULL;78}79 80void arena_free(char *h_ptr) {81  Header *header = (Header *)(h_ptr - sizeof(Header));82  header->is_free = 1;83  arena_coalescing(header);84}85void check_arena_block() {86  char *current = g_arena.start;87  int block_num = 0;88  while (current < g_arena.cursor) {89    Header *header = (Header *)current;90    printf("Block %d: %zu bytes, %s\n", block_num, header->size,91           header->is_free ? "FREE" : "USED");92    current += block_span(header->size);93    block_num++;94  }95}96 97int main() {98  void *mem = mmap(NULL, ARENA_SIZE, PROT_READ | PROT_WRITE,99                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);100 101  if (mem == MAP_FAILED) {102    return -1;103  }104 105  g_arena.start = mem;106  g_arena.cursor = mem;107  g_arena.end = mem + ARENA_SIZE;108 109  char *a = arena_alloc(512);110  char *b = arena_alloc(512);111  char *c = arena_alloc(1024);112 113  printf("a: %p\n", a);114  printf("b: %p\n", b);115 116  unsigned long diff = b - a;117  printf("\nAddr difference: 0x%lx (%ld bytes)\n", diff, diff);118  printf("Expected: sizeof(Header) + user_size = %zu + 512 = %zu\n",119         sizeof(Header), block_span(512));120 121  arena_free(b);122  arena_free(a);123 124  printf("\nArena state after freeing:\n");125  check_arena_block();126 127  munmap(mem, ARENA_SIZE);128 129  return 0;130}