about summary refs log tree commit diff stats
path: root/arena.c
blob: 3e1a57c641242a30c7e8fb1e2c8857a73466787a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "arena.h"
#include <stdlib.h>
#define PAGE_SIZE 4096
enum {
	ARENA_SUCCESS = 0,
	ARENA_EXPAND,
	ARENA_FAILURE,
}
int arena_errno;
arena_t* arena_create_sized(size_t size){
	arena_t* arena = (arena_t*) calloc(1, sizeof(arena_t*));
	if (!arena) {
		arena_errno = ARENA_FAILURE;
		return 0;
	}
	arena->memory = (uint8_t*) calloc(1, size);
	arena->size = size;
	if (!arena->memory) {
		free(arena);
		arena_errno = ARENA_FAILURE;
		return 0;
	}
	arena_errno = ARENA_SUCCESS;
	return arena;
}
arena_t* arena_create() {
	return arena_create_sized(PAGE_SIZE);
}
void* arena_malloc(arena_t* arena, size_t size) {
	arena_t* head = arena;
	arena_t* tail;
	do {
		if ((arena->size - arena->fill) > size) {
			arena->fill += size;
			// NOTE: do not overwrite ARENA_EXPAND code
			if (arena_errno != ARENA_EXPAND) arena_errno = ARENA_SUCCESS;
			return arena->memory + (arena->fill - size);
		}
	} while ((arena = arena->next) != 0);
	tail = arena_create();
	if (tail == 0) {
		// NOTE: `arena_errno` is already set from `arena_create`
		return 0;
	}
	arena_errno = ARENA_EXPAND;
	return arena_malloc(tail, size);
}
void arena_destroy(arena_t* arena) {
	arena_t* tail = arena;
	do {
		free(tail->memory);
		free(tail);
		tail = tail->next;
	} while (tail != 0);
	arena_errno = ARENA_SUCCESS;
}