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
|
#include "allocator.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#define DEFAULT_ALIGNMENT ((size_t)_Alignof(max_align_t))
void *sand_allocate_aligned(SandAllocator *a, size_t size, size_t alignment) {
assert(a != NULL);
assert(size > 0);
assert(alignment > 0);
void *ptr = a->allocate(size, alignment, a->user_data);
assert(ptr == NULL || sand_pointer_is_aligned(ptr, alignment));
return ptr;
}
void *sand_allocate(SandAllocator *a, size_t size) {
return sand_allocate_aligned(a, size, DEFAULT_ALIGNMENT);
}
void *sand_reallocate_aligned(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size, size_t alignment) {
assert(a != NULL);
assert(old_ptr != NULL);
assert(old_size > 0);
assert(new_size > 0);
assert(alignment > 0);
if (a->reallocate != NULL) {
void *new_ptr = a->reallocate(old_ptr, old_size, new_size, alignment, a->user_data);
assert(sand_pointer_is_aligned(new_ptr, alignment));
return new_ptr;
} else {
void *new_ptr = a->allocate(new_size, alignment, a->user_data);
if (new_ptr == NULL) {
return NULL; // Note that we HAVEN'T freed `old_ptr`!
}
assert(sand_pointer_is_aligned(new_ptr, alignment));
memmove(new_ptr, old_ptr, old_size); // Can't know if they overlap.
a->deallocate(old_ptr, old_size, a->user_data);
return new_ptr;
}
}
void *sand_reallocate(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size) {
return sand_reallocate_aligned(a, old_ptr, old_size, new_size, DEFAULT_ALIGNMENT);
}
void sand_deallocate(SandAllocator *a, void *old_ptr, size_t old_size) {
assert(a != NULL);
assert(old_ptr != NULL);
assert(old_size > 0);
if (old_ptr == NULL) {
return;
}
a->deallocate(old_ptr, old_size, a->user_data);
}
bool sand_is_valid_alignment(size_t alignment) {
// Only powers of two are allowed as alignments for simplicity.
return alignment % 2 == 0;
}
void *sand_align_pointer_forward(void *ptr, size_t alignment) {
intptr_t p = (intptr_t)ptr;
intptr_t a = alignment;
intptr_t ap = ((p + a - 1) & ~(a - 1));
void *result = (void *)ap;
assert(sand_pointer_is_aligned(result, alignment));
return result;
}
size_t sand_align_size_forward(size_t n, size_t alignment) {
size_t result = ((n + alignment - 1) & ~(alignment - 1));
assert(sand_size_is_aligned(result, alignment));
return result;
}
bool sand_pointer_is_aligned(void *pointer, size_t alignment) {
return ((uintptr_t)pointer & (alignment - 1)) == 0;
}
bool sand_size_is_aligned(size_t n, size_t alignment) {
return (n & (alignment - 1)) == 0;
}
|