kiba-engine
allocator.c
Go to the documentation of this file.
1 
9 
11 #include <kiba/allocators/linear.h>
12 #include <kiba/allocators/system.h>
13 #include <kiba/core/log.h>
14 #include <kiba/core/memory.h>
15 
30 usize allocator_managed_block_required_size(usize size, usize alignment);
46 void *allocator_managed_block_create(void *allocated, usize size, usize alignment);
64 void *allocator_managed_block_extract(const void *block, usize *size, usize *alignment, usize *offset);
65 
66 b8 allocator_create(allocator *alloc, allocator_type type, usize size) {
67  switch (type) {
68  case ALLOCATOR_LINEAR:
70  case ALLOCATOR_FREE_LIST:
72  case ALLOCATOR_SYSTEM:
74  }
75  KB_ERROR("no valid core allocator type selected: {i32}", type);
76  return false;
77 }
78 
79 b8 allocator_create_custom(allocator *alloc, allocator_impl_create_fn create_fn, usize size) {
80  KB_ASSERT(alloc != KB_NULL, "allocator pointer must be valid");
81  return create_fn(alloc, size);
82 }
83 
85  KB_ASSERT(alloc != KB_NULL && alloc->state != KB_NULL && alloc->impl.destroy != KB_NULL,
86  "allocator must have initialized state");
87  alloc->impl.destroy(alloc);
89  memory_zero(alloc, sizeof(allocator));
90 }
91 
92 void *allocator_allocate(allocator *alloc, usize size) { return allocator_allocate_aligned(alloc, size, 1); }
93 
94 void *allocator_allocate_aligned(allocator *alloc, usize size, usize alignment) {
95  KB_ASSERT(alloc != KB_NULL && alloc->state != KB_NULL && alloc->impl.allocate != KB_NULL,
96  "allocator must have initialized state");
97  KB_ASSERT(size != 0, "size to allocate must not be 0");
98  KB_ASSERT(alignment != 0, "alignment for allocation must not be 0"); // TODO maybe also verify power of 2
99  usize actual_size = allocator_managed_block_required_size(size, alignment);
100  void *block = alloc->impl.allocate(alloc, actual_size);
101  if (block != KB_NULL) {
102  block = allocator_managed_block_create(block, size, alignment);
103  }
104  return block;
105 }
106 
107 void *allocator_reallocate(allocator *alloc, void *original, usize new_size) {
108  return allocator_reallocate_aligned(alloc, original, new_size, 0);
109 }
110 
111 void *allocator_reallocate_aligned(allocator *alloc, void *original, usize new_size, usize alignment) {
112  KB_ASSERT(
113  alloc != KB_NULL && alloc->state != KB_NULL && alloc->impl.allocate != KB_NULL && alloc->impl.free != KB_NULL,
114  "allocator must have initialized state");
115  KB_ASSERT(original != KB_NULL, "original pointer for reallocate must not be nullptr");
116  KB_ASSERT(new_size != 0, "new size for reallocation must not be 0");
117  usize original_size, original_alignment, original_offset;
118  void *actual_original =
119  allocator_managed_block_extract(original, &original_size, &original_alignment, &original_offset);
120  if (!alignment) {
121  alignment = original_alignment; // ensure new block retains original alignment
122  }
123 
124  usize actual_new_size = allocator_managed_block_required_size(new_size, alignment);
125  void *new_block = alloc->impl.allocate(alloc, actual_new_size);
126  if (new_block != KB_NULL) {
127  new_block = allocator_managed_block_create(new_block, new_size, alignment);
128  memory_copy(new_block, original, KB_MIN(new_size, original_size - original_offset));
129  alloc->impl.free(alloc, actual_original, original_size);
130  }
131  return new_block;
132 }
133 
134 void allocator_free(allocator *alloc, void *mem) {
135  KB_ASSERT(alloc != KB_NULL && alloc->state != KB_NULL && alloc->impl.free != KB_NULL,
136  "allocator must have initialized state");
137  KB_ASSERT(mem != KB_NULL, "memory to free must not be nullptr");
138  usize size, alignment, offset;
139  void *actual_mem = allocator_managed_block_extract(mem, &size, &alignment, &offset);
140  alloc->impl.free(alloc, actual_mem, size);
141 }
142 
144  KB_ASSERT(alloc != KB_NULL && alloc->state != KB_NULL && alloc->impl.free_all != KB_NULL,
145  "allocator must have initialized state");
146  alloc->impl.free_all(alloc);
147 }
148 
153  allocator_impl_free_all_fn free_all) {
154  KB_ASSERT(alloc != KB_NULL, "allocator pointer must be valid");
155  alloc->impl.destroy = destroy;
156  alloc->impl.allocate = allocate;
157  alloc->impl.free = free;
158  alloc->impl.free_all = free_all;
159 }
160 
177 #define KB_ALLOCATOR_MANAGED_BLOCK_SIZE (3 * sizeof(usize))
178 
179 usize allocator_managed_block_required_size(usize size, usize alignment) {
180  KB_ASSERT_DEBUG(size != 0, "size of managed block must not be 0");
181  KB_ASSERT_DEBUG(alignment != 0, "alignment of managed block must not be 0");
182  return size + KB_ALLOCATOR_MANAGED_BLOCK_SIZE + alignment - 1;
183 }
184 
185 void *allocator_managed_block_create(void *allocated, usize size, usize alignment) {
186  KB_ASSERT_DEBUG(allocated != KB_NULL, "pointer to block to manage must be valid");
187  void *new_addr = memory_aligned_address((u8 *) allocated + KB_ALLOCATOR_MANAGED_BLOCK_SIZE, alignment);
188  usize *header = new_addr;
189  header[-1] = allocator_managed_block_required_size(size, alignment);
190  header[-2] = alignment;
191  header[-3] = (uptr) new_addr - (uptr) allocated;
192  return new_addr;
193 }
194 
195 void *allocator_managed_block_extract(const void *block, usize *size, usize *alignment, usize *offset) {
196  KB_ASSERT_DEBUG(block != KB_NULL, "pointer to user part of managed block must be valid");
197  const usize *data = block;
198  *size = data[-1];
199  *alignment = data[-2];
200  *offset = data[-3];
201  return (u8 *) block - *offset;
202 }
203 
204 #undef KB_ALLOCATOR_MANAGED_BLOCK_SIZE
void * allocator_allocate(allocator *alloc, usize size)
Allocate unaligned memory.
Definition: allocator.c:92
b8 allocator_create_custom(allocator *alloc, allocator_impl_create_fn create_fn, usize size)
Create an allocator based on a custom create function.
Definition: allocator.c:79
void * allocator_managed_block_extract(const void *block, usize *size, usize *alignment, usize *offset)
extract metadata from managed block.
Definition: allocator.c:195
usize allocator_managed_block_required_size(usize size, usize alignment)
Calculate required size of an managed block based on size and alignment.
Definition: allocator.c:179
void * allocator_managed_block_create(void *allocated, usize size, usize alignment)
Create managed block in pre-allocated memory.
Definition: allocator.c:185
void * allocator_allocate_aligned(allocator *alloc, usize size, usize alignment)
Allocate aligned memory.
Definition: allocator.c:94
void * allocator_reallocate(allocator *alloc, void *original, usize new_size)
Reallocate memory to unaligned block.
Definition: allocator.c:107
void allocator_free(allocator *alloc, void *mem)
Give back memory to the allocator.
Definition: allocator.c:134
#define KB_ALLOCATOR_MANAGED_BLOCK_SIZE
Size of the managed block attached to each allocation.
Definition: allocator.c:177
b8 allocator_create(allocator *alloc, allocator_type type, usize size)
Create an allocator of a specific type.
Definition: allocator.c:66
void allocator_destroy(allocator *alloc)
Destroy an allocator.
Definition: allocator.c:84
void allocator_free_all(allocator *alloc)
Reset the allocator.
Definition: allocator.c:143
void allocator_implementation(allocator *alloc, allocator_impl_destroy_fn destroy, allocator_impl_allocate_fn allocate, allocator_impl_free_fn free, allocator_impl_free_all_fn free_all)
Set allocator implementation.
Definition: allocator.c:149
void * allocator_reallocate_aligned(allocator *alloc, void *original, usize new_size, usize alignment)
Rellocate aligned memory.
Definition: allocator.c:111
Central header providing allocator functionality.
allocator_type
Available allocator types.
Definition: allocator.h:18
void(* allocator_impl_free_all_fn)(struct allocator *alloc)
Give all allocated memory back to the allocator.
Definition: allocator.h:68
void(* allocator_impl_free_fn)(struct allocator *alloc, void *mem, usize size)
Give memory back to the allocator.
Definition: allocator.h:62
void(* allocator_impl_destroy_fn)(struct allocator *alloc)
Destroy the allocator.
Definition: allocator.h:46
b8(* allocator_impl_create_fn)(struct allocator *alloc, usize size)
Create a specific allocator.
Definition: allocator.h:38
void *(* allocator_impl_allocate_fn)(struct allocator *alloc, usize size)
Allocate memory.
Definition: allocator.h:54
void * memory_copy(void *dst, const void *src, usize size)
Copy memory.
Definition: memory.c:83
void * memory_aligned_address(void *addr, usize alignment)
Calculate properly aligned memory block address.
Definition: memory.c:85
void * memory_zero(void *mem, usize size)
Zero out memory.
Definition: memory.c:79
Lightweight layer between platform and other engine components to enable tracing/monitoring.
#define KB_MIN(x, y)
Ternary to get the minimum of two numbers.
Definition: defines.h:35
#define KB_NULL
Value of an invalid ptr (nullptr).
Definition: defines.h:18
b8 free_list_allocator_create(allocator *alloc, usize size)
Definition: free_list.c:268
Function signatures for free list based allocator implementation.
b8 linear_allocator_create(allocator *alloc, usize size)
Definition: linear.c:60
Function signatures for linear allocator implementation.
Logging system.
#define KB_ASSERT(expr,...)
Perform runtime assertion and log failures.
Definition: log.h:133
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142
#define KB_ASSERT_DEBUG(expr,...)
Perform runtime debug assertion and log failures.
Definition: log.h:165
allocator_impl_allocate_fn allocate
Allocator's allocate implementation.
Definition: allocator.h:75
allocator_impl_free_fn free
Allocator's free implementation.
Definition: allocator.h:77
allocator_impl_destroy_fn destroy
Allocator's destroy implementation.
Definition: allocator.h:73
allocator_impl_free_all_fn free_all
Allocator's free_all implementation.
Definition: allocator.h:79
Central allocator structure.
Definition: allocator.h:87
void * state
Type specific state of the allocator.
Definition: allocator.h:91
allocator_impl impl
Type specific implementation of the allocator.
Definition: allocator.h:89
b8 system_allocator_create(allocator *alloc, usize size)
Definition: system.c:10
Function signatures for system allocator implementation.