Skip to content

Commit 33a61e2

Browse files
darksylincSpartan322
authored andcommitted
Add aligned_static functions to Memory
(cherry picked from commit godotengine/godot@364f916)
1 parent 4a499ed commit 33a61e2

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

core/os/memory.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include <stdio.h>
3939
#include <stdlib.h>
40+
#include <string.h>
4041

4142
void *operator new(size_t p_size, const char *p_description) {
4243
return Memory::alloc_static(p_size, false);
@@ -67,6 +68,38 @@ SafeNumeric<uint64_t> Memory::max_usage;
6768

6869
SafeNumeric<uint64_t> Memory::alloc_count;
6970

71+
inline bool is_power_of_2(size_t x) { return x && ((x & (x - 1U)) == 0U); }
72+
73+
void *Memory::alloc_aligned_static(size_t p_bytes, size_t p_alignment) {
74+
DEV_ASSERT(is_power_of_2(p_alignment));
75+
76+
void *p1, *p2;
77+
if ((p1 = (void *)malloc(p_bytes + p_alignment - 1 + sizeof(uint32_t))) == nullptr) {
78+
return nullptr;
79+
}
80+
81+
p2 = (void *)(((uintptr_t)p1 + sizeof(uint32_t) + p_alignment - 1) & ~((p_alignment)-1));
82+
*((uint32_t *)p2 - 1) = (uint32_t)((uintptr_t)p2 - (uintptr_t)p1);
83+
return p2;
84+
}
85+
86+
void *Memory::realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment) {
87+
if (p_memory == nullptr) {
88+
return alloc_aligned_static(p_bytes, p_alignment);
89+
}
90+
91+
void *ret = alloc_aligned_static(p_bytes, p_alignment);
92+
memcpy(ret, p_memory, p_prev_bytes);
93+
free_aligned_static(p_memory);
94+
return ret;
95+
}
96+
97+
void Memory::free_aligned_static(void *p_memory) {
98+
uint32_t offset = *((uint32_t *)p_memory - 1);
99+
void *p = (void *)((uint8_t *)p_memory - offset);
100+
free(p);
101+
}
102+
70103
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
71104
#ifdef DEBUG_ENABLED
72105
bool prepad = true;

core/os/memory.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ class Memory {
6464
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
6565
static void free_static(void *p_ptr, bool p_pad_align = false);
6666

67+
// ↓ return value of alloc_aligned_static
68+
// ┌─────────────────┬─────────┬─────────┬──────────────────┐
69+
// │ padding (up to │ uint32_t│ void* │ padding (up to │
70+
// │ p_alignment - 1)│ offset │ p_bytes │ p_alignment - 1) │
71+
// └─────────────────┴─────────┴─────────┴──────────────────┘
72+
//
73+
// alloc_aligned_static will allocate p_bytes + p_alignment - 1 + sizeof(uint32_t) and
74+
// then offset the pointer until alignment is satisfied.
75+
//
76+
// This offset is stored before the start of the returned ptr so we can retrieve the original/real
77+
// start of the ptr in order to free it.
78+
//
79+
// The rest is wasted as padding in the beginning and end of the ptr. The sum of padding at
80+
// both start and end of the block must add exactly to p_alignment - 1.
81+
//
82+
// p_alignment MUST be a power of 2.
83+
static void *alloc_aligned_static(size_t p_bytes, size_t p_alignment);
84+
static void *realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment);
85+
// Pass the ptr returned by alloc_aligned_static to free it.
86+
// e.g.
87+
// void *data = realloc_aligned_static( bytes, 16 );
88+
// free_aligned_static( data );
89+
static void free_aligned_static(void *p_memory);
90+
6791
static uint64_t get_mem_available();
6892
static uint64_t get_mem_usage();
6993
static uint64_t get_mem_max_usage();

0 commit comments

Comments
 (0)