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
|
#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 {
size_t *start;
size_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;
}
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;
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;
}
}
}
|