diff options
| author | Feoramund <161657516+Feoramund@users.noreply.github.com> | 2025-06-19 19:36:55 -0400 |
|---|---|---|
| committer | Feoramund <161657516+Feoramund@users.noreply.github.com> | 2025-06-19 19:41:38 -0400 |
| commit | 57e2d8f1ddf356a0bfabec7630c1e7ff0199f800 (patch) | |
| tree | 22457163fad565583fbc0968f098e07286ddded4 | |
| parent | 4e9f15965a9aba66833a1b377094d8b1544f155c (diff) | |
mem: Fix `Buddy_Allocator` size calculation to truly include alignment
This didn't take into account the size of the header plus the size of
the allocation itself by virtue of `align_forward_uint`; this could
result in no change if `size` was equal to `b.alignment` because the
number is aligned, and if `actual_size` and `size` ended up being equal,
no additional space would be requested.
This meant that a block would end up being allocated on top of its
buddy's head.
Fixes #3435
| -rw-r--r-- | core/mem/allocators.odin | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index a40ab245e..e3b96a8f7 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -2247,12 +2247,14 @@ Get required block size to fit in the allocation as well as the alignment paddin */ @(require_results) buddy_block_size_required :: proc(b: ^Buddy_Allocator, size: uint) -> uint { - size := size - actual_size := b.alignment - size += size_of(Buddy_Block) - size = align_forward_uint(size, b.alignment) - for size > actual_size { - actual_size <<= 1 + assert(size > 0) + // NOTE: `size_of(Buddy_Block)` will be accounted for in `b.alignment`. + // This calculation is also previously guarded against being given a `size` + // 0 by `buddy_allocator_alloc_bytes_non_zeroed` checking for that. + actual_size := b.alignment + size + if intrinsics.count_ones(actual_size) != 1 { + // We're not a power of two. Let's fix that. + actual_size = 1 << (size_of(uint) * 8 - intrinsics.count_leading_zeros(actual_size)) } return actual_size } |