about summary refs log tree commit diff stats
path: root/src/salloc.c
blob: eada8fada2228fab9a4a52b48372696e3db972f1 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "salloc.h"

#include <stdlib.h>
#include <stdint.h>
#include <string.h>

struct spicy_allocation {
	size_t pagenum;
	size_t size;
	size_t *start;
	size_t *prev;
};

struct spicy_page {
	uint8_t *start;
	uint8_t *current;
	size_t free;
};

static struct {
	size_t pagecount;
	size_t pagesize;
	size_t *c;
	size_t max_pages;
	size_t max_allocs;
	size_t csize;
	struct spicy_page *pages;
	struct spicy_allocation *allocs;
} spicy_arena = {
	.pagecount = 0,
	.pagesize = 10240,
	.c = NULL,
	.max_pages = 1024,
	.max_allocs = 10240,
	.csize = (1024 * sizeof(struct spicy_page)) + (1024 * sizeof(struct spicy_allocation)),
	.pages = NULL,
	.allocs = NULL
};

int salloc_configure(size_t pagesize, size_t max_pages, size_t max_allocs) {
	if (spicy_arena.c != NULL) return -1; // allocator already used!
	spicy_arena.pagesize = pagesize;
	spicy_arena.max_pages = max_pages;
	spicy_arena.max_allocs = max_allocs;
	spicy_arena.csize = max_pages + max_allocs;
	return 0;
}

void *salloc(size_t size) {
	if (spicy_arena.c == NULL) {
		spicy_arena.c = malloc(spicy_arena.csize);
		if (spicy_arena.c == NULL) return NULL;
		memset(spicy_arena.c, 0 , spicy_arena.csize);
	}
	if (spicy_arena.pages == NULL) {
		spicy_arena.pages = (struct spicy_page *)spicy_arena.c;
	}
	if (spicy_arena.allocs == NULL) {
		spicy_arena.allocs = (struct spicy_allocation *)(spicy_arena.c + (spicy_arena.max_pages * sizeof(struct spicy_page)));
	}
	if (spicy_arena.pagecount == 0) {
		spicy_arena.pages[0].start = malloc(spicy_arena.pagesize);
		if (spicy_arena.pages[0].start == NULL) return NULL;
		spicy_arena.pages[0].current = spicy_arena.pages[0].start;
		spicy_arena.pages[0].free = spicy_arena.pagesize;
		spicy_arena.pagecount++;
	}
	// This is inefficient!
	for (size_t i = 0; i < spicy_arena.max_allocs; i++) {
		if (spicy_arena.allocs[i].start == NULL) {
			if (spicy_arena.allocs[i].size >= size) {
				spicy_arena.allocs[i].start = spicy_arena.allocs[i].prev;
				return (void *)spicy_arena.allocs[i].start;
			}
			if (spicy_arena.allocs[i].size == 0) {
				for (size_t x = 0; x < spicy_arena.pagecount; x++) {
					if (spicy_arena.pages[x].free >= size) {
						void *ret = spicy_arena.pages[x].current;
						spicy_arena.pages[x].current += size;
						spicy_arena.pages[x].free -= size;
						return ret;
					}
				}
			spicy_arena.pages[spicy_arena.pagecount].start = malloc(spicy_arena.pagesize);
			if (spicy_arena.pages[spicy_arena.pagecount].start == NULL) return NULL;
			void *ret = spicy_arena.pages[spicy_arena.pagecount].start;
			spicy_arena.pages[spicy_arena.pagecount].current = spicy_arena.pages[spicy_arena.pagecount].start + size;
			spicy_arena.pages[spicy_arena.pagecount].free = spicy_arena.pagesize - size;
			spicy_arena.pagecount++;
			return ret;
			}
		}
	}
	return NULL;
}

void *scalloc(size_t count, size_t size) {
	void *ret = salloc(count * size);
	if (ret != NULL) {
		memset(ret, 0, count * size);
		return ret;
	}
	return NULL;
}

void sfree(void *ptr) {
	if (ptr == NULL) return;
	if (spicy_arena.allocs == NULL) return;
	for (size_t i = 0; i < spicy_arena.max_allocs; i++) {
		if (ptr == spicy_arena.allocs[i].start) {
			spicy_arena.allocs[i].prev = spicy_arena.allocs[i].start;
			spicy_arena.allocs[i].start = NULL;
			ptr = NULL;
		}
	}
}

void sfreea() {
	if (spicy_arena.pages != NULL && spicy_arena.c != NULL) {
		for (size_t i = 0; i < spicy_arena.pagecount; i++) {
			free(spicy_arena.pages[i].start);
		}
		free(spicy_arena.c);
		spicy_arena.pagecount = 0;
		spicy_arena.pages = NULL;
		spicy_arena.allocs = NULL;
	}
}