Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions src/util/rbs_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ static size_t get_system_page_size(void) {
#endif
}

static inline uintptr_t rbs_align_up_uintptr(uintptr_t value, size_t alignment) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name makes it sound like it's aligning up to the nearest uintptr's alignment (i.e. to the next 8 bytes on 64 bit systems)

Suggested change
static inline uintptr_t rbs_align_up_uintptr(uintptr_t value, size_t alignment) {
static inline uintptr_t rbs_align_up(uintptr_t value, size_t alignment) {

// alignment must be a non-zero power of two
rbs_assert(alignment != 0 && (alignment & (alignment - 1)) == 0, "alignment must be a non-zero power of two. alignment: %zu", alignment);
return (value + (alignment - 1)) & ~(uintptr_t) (alignment - 1);
}

static rbs_allocator_page_t *rbs_allocator_page_new(size_t payload_size) {
const size_t page_header_size = sizeof(rbs_allocator_page_t);

Expand Down Expand Up @@ -98,10 +104,9 @@ void *rbs_allocator_realloc_impl(rbs_allocator_t *allocator, void *ptr, size_t o

// Allocates `size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t alignment) {
rbs_assert(size % alignment == 0, "size must be a multiple of the alignment. size: %zu, alignment: %zu", size, alignment);

if (allocator->default_page_payload_size < size) { // Big allocation, give it its own page.
rbs_allocator_page_t *new_page = rbs_allocator_page_new(size);
// Add padding to ensure we can align the start pointer within this page
rbs_allocator_page_t *new_page = rbs_allocator_page_new(size + (alignment - 1));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why -1?


// This simple allocator can only put small allocations into the head page.
// Naively prepending this large allocation page to the head of the allocator before the previous head page
Expand All @@ -120,21 +125,29 @@ void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t
new_page->next = allocator->page->next;
allocator->page->next = new_page;

uintptr_t pointer = (uintptr_t) new_page + sizeof(rbs_allocator_page_t);
return (void *) pointer;
uintptr_t base = (uintptr_t) new_page + sizeof(rbs_allocator_page_t);
uintptr_t aligned_ptr = rbs_align_up_uintptr(base, alignment);
return (void *) aligned_ptr;
}

rbs_allocator_page_t *page = allocator->page;
if (page->used + size > page->size) {
uintptr_t base = (uintptr_t) page + sizeof(rbs_allocator_page_t);

// Compute aligned offset within the payload
size_t used_aligned = (size_t) (rbs_align_up_uintptr(base + page->used, alignment) - base);
Comment on lines +136 to +137
Copy link

@amomchilov amomchilov Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of tricky, I think it's easier to follow if you write this in terms of page->used + needed_aligned_size, than it is to align up the base + header_size + page->size and then add a non-padded size


if (used_aligned + size > page->size) {
// Not enough space. Allocate a new small page and prepend it to the allocator's linked list.
rbs_allocator_page_t *new_page = rbs_allocator_page_new(allocator->default_page_payload_size);
new_page->next = allocator->page;
allocator->page = new_page;
page = new_page;
base = (uintptr_t) page + sizeof(rbs_allocator_page_t);
used_aligned = (size_t) (rbs_align_up_uintptr(base, alignment) - base); // start of fresh page (usually 0 if header is aligned)
}

uintptr_t pointer = (uintptr_t) page + sizeof(rbs_allocator_page_t) + page->used;
page->used += size;
uintptr_t pointer = base + used_aligned;
page->used = used_aligned + size;
return (void *) pointer;
}

Expand Down