diff --git a/src/util/HugeAllocator.cxx b/src/util/HugeAllocator.cxx index 52b53a7ef..bc5aeff27 100644 --- a/src/util/HugeAllocator.cxx +++ b/src/util/HugeAllocator.cxx @@ -3,6 +3,7 @@ #include "HugeAllocator.hxx" #include "system/VmaName.hxx" +#include "util/RoundPowerOfTwo.hxx" #include @@ -26,8 +27,7 @@ AlignToPageSize(size_t size) noexcept if (page_size <= 0) return size; - size_t ps(page_size); - return (size + ps - 1) / ps * ps; + return RoundUpToPowerOfTwo(size, static_cast(page_size)); } std::span diff --git a/src/util/RoundPowerOfTwo.hxx b/src/util/RoundPowerOfTwo.hxx new file mode 100644 index 000000000..1a9aafbb2 --- /dev/null +++ b/src/util/RoundPowerOfTwo.hxx @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann + +#pragma once + +#include + +template +constexpr T +RoundUpToPowerOfTwo(T value) noexcept +{ + if (value <= 0) + return 1; + + --value; + + for (unsigned bits = 1; bits < sizeof(T) * 8; bits <<= 1) + value |= value >> bits; + + ++value; + + return value; +} + +static_assert(RoundUpToPowerOfTwo(0U) == 1U); +static_assert(RoundUpToPowerOfTwo(2U) == 2U); +static_assert(RoundUpToPowerOfTwo(3U) == 4U); +static_assert(RoundUpToPowerOfTwo(4U) == 4U); +static_assert(RoundUpToPowerOfTwo(5U) == 8U); +static_assert(RoundUpToPowerOfTwo(0x7fffU) == 0x8000U); +static_assert(RoundUpToPowerOfTwo(0x7ffffU) == 0x80000U); +static_assert(RoundUpToPowerOfTwo(0x1000000000000000ULL) == 0x1000000000000000ULL); +static_assert(RoundUpToPowerOfTwo(0x1fffffffffffffffULL) == 0x2000000000000000ULL); +static_assert(RoundUpToPowerOfTwo(0x7fffffffffffffffULL) == 0x8000000000000000ULL); +static_assert(RoundUpToPowerOfTwo(0x8000000000000000ULL) == 0x8000000000000000ULL); + +template +constexpr T +RoundUpToPowerOfTwo(T value, T power_of_two) noexcept +{ + return ((value - 1) | (power_of_two - 1)) + 1; +} + +template +constexpr T +RoundDownToPowerOfTwo(T value, T power_of_two) noexcept +{ + return value & ~(power_of_two - 1); +}