-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasealloc.c
More file actions
100 lines (89 loc) · 2.25 KB
/
basealloc.c
File metadata and controls
100 lines (89 loc) · 2.25 KB
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
#define CS0019_DISABLE 1
#include "cs0019.h"
#include <stdio.h>
// This file contains a base memory allocator guaranteed not to
// overwrite freed allocations. No need to understand it.
typedef struct base_allocation {
void *ptr;
size_t sz;
} base_allocation;
static base_allocation *allocs;
static size_t nallocs;
static size_t alloc_capacity;
static size_t *frees;
static size_t nfrees;
static size_t free_capacity;
static int disabled;
static unsigned alloc_random(void) {
static uint64_t x = 8973443640547502487ULL;
x = x * 6364136223846793005ULL + 1ULL;
return x >> 32;
}
static void base_alloc_atexit(void);
void *base_malloc(size_t sz) {
if (disabled) {
return malloc(sz);
}
static int base_alloc_atexit_installed = 0;
if (!base_alloc_atexit_installed) {
atexit(base_alloc_atexit);
base_alloc_atexit_installed = 1;
}
unsigned r = alloc_random();
// try to use a previously-freed block 75% of the time
if (r % 4 != 0) {
for (unsigned try = 0; try < 10 && try < nfrees; ++try) {
size_t freenum = alloc_random() % nfrees;
size_t i = frees[freenum];
if (allocs[i].sz >= sz) {
frees[freenum] = frees[nfrees - 1];
--nfrees;
return allocs[i].ptr;
}
}
}
// need a new allocation
if (nallocs == alloc_capacity) {
alloc_capacity = alloc_capacity ? alloc_capacity * 2 : 64;
allocs = realloc(allocs, alloc_capacity * sizeof(base_allocation));
if (!allocs) {
ABORT();
}
}
void *ptr = malloc(sz);
if (ptr) {
allocs[nallocs].ptr = ptr;
allocs[nallocs].sz = sz;
++nallocs;
}
return ptr;
}
void base_free(void *ptr) {
if (disabled || !ptr) {
free(ptr);
return;
}
if (nfrees == free_capacity) {
free_capacity = free_capacity ? free_capacity * 2 : 64;
frees = realloc(frees, free_capacity * sizeof(size_t));
if (!frees) {
ABORT();
}
}
for (size_t i = 0; i < nallocs; ++i) {
if (allocs[i].ptr == ptr) {
frees[nfrees] = i;
++nfrees;
return;
}
}
// if we get here, invalid free; silently ignore it
}
void base_malloc_disable(int d) { disabled = d; }
static void base_alloc_atexit(void) {
for (size_t i = 0; i < nfrees; ++i) {
free(allocs[frees[i]].ptr);
}
free(frees);
free(allocs);
}