https://gcc.gnu.org/g:7a878ba615c2c51ea9cf89142033c5e1ad71795e
commit r16-2123-g7a878ba615c2c51ea9cf89142033c5e1ad71795e Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jul 9 10:14:23 2025 +0100 libstdc++: Fix memory_resource.cc bootstrap failure for non-gthreads targets The new choose_block_size function added in r16-2112-gac2fb60a67d6d1 was defined inside an #ifdef _GLIBCXX_HAS_GTHREADS group, which means that it's not available for single-threaded targets, and so can't be used by unsynchronized_pool_resource. Move it before that preprocessor group so it's always defined. libstdc++-v3/ChangeLog: * src/c++17/memory_resource.cc: Adjust indentation of unnamed namespaces. (pool_sizes): Add comment. (choose_block_size): Move outside preprocessor group for gthreads targets. * testsuite/20_util/synchronized_pool_resource/118681.cc: Require gthreads. Diff: --- libstdc++-v3/src/c++17/memory_resource.cc | 66 +++++++++++++--------- .../20_util/synchronized_pool_resource/118681.cc | 1 + 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index fddfe2c7dd98..c61569f249ad 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -182,8 +182,8 @@ namespace pmr // versions will not use this symbol. monotonic_buffer_resource::~monotonic_buffer_resource() { release(); } - namespace { - +namespace +{ // aligned_size<N> stores the size and alignment of a memory allocation. // The size must be a multiple of N, leaving the low log2(N) bits free // to store the base-2 logarithm of the alignment. @@ -221,7 +221,7 @@ namespace pmr return (n + alignment - 1) & ~(alignment - 1); } - } // namespace +} // namespace // Memory allocated by the upstream resource is managed in a linked list // of _Chunk objects. A _Chunk object recording the size and alignment of @@ -307,8 +307,8 @@ namespace pmr // Helper types for synchronized_pool_resource & unsynchronized_pool_resource - namespace { - +namespace +{ // Simple bitset with runtime size. // Tracks which blocks in a pool chunk are used/unused. struct bitset @@ -636,7 +636,7 @@ namespace pmr static_assert(sizeof(big_block) == (2 * sizeof(void*))); - } // namespace +} // namespace // A pool that serves blocks of a particular size. // Each pool manages a number of chunks. @@ -868,7 +868,16 @@ namespace pmr using big_block::big_block; }; - namespace { +namespace +{ + // N.B. it is important that we don't skip any power of two sizes if there + // is a non-power of two size between them, e.g. must not have pool sizes + // of 24 and 40 without having a pool size of 32. Otherwise an allocation + // of 32 bytes with alignment 16 would choose the 40-byte pool which is not + // correctly aligned for 16-byte alignment. It would be OK (but suboptimal) + // to have no pool of size 32 if we have pool sizes of 16 and 64 and no + // non-power of two sizes between those, because the example of (32, 16) + // would choose the 64-byte pool, which would be correctly aligned. constexpr size_t pool_sizes[] = { 8, 16, 24, @@ -983,7 +992,7 @@ namespace pmr using exclusive_lock = lock_guard<shared_mutex>; #endif - } // namespace +} // namespace __pool_resource:: __pool_resource(const pool_options& opts, memory_resource* upstream) @@ -1075,12 +1084,33 @@ namespace pmr return p; } + // Determine the appropriate allocation size, rounding up to a multiple + // of the alignment if needed. + static inline size_t + choose_block_size(size_t bytes, size_t alignment) + { + if (bytes == 0) [[unlikely]] + return alignment; + + // Use bit_ceil in case alignment is invalid (i.e. not a power of two). + size_t mask = std::__bit_ceil(alignment) - 1; + // Round up to a multiple of alignment. + size_t block_size = (bytes + mask) & ~mask; + + if (block_size >= bytes) [[likely]] + return block_size; + + // Wrapped around to zero, bytes must have been impossibly large. + return numeric_limits<size_t>::max(); + } + + #ifdef _GLIBCXX_HAS_GTHREADS // synchronized_pool_resource members. /* Notes on implementation and thread safety: * - * Each synchronized_pool_resource manages an linked list of N+1 _TPools + * Each synchronized_pool_resource manages a linked list of N+1 _TPools * objects, where N is the number of threads using the pool resource. * Each _TPools object has its own set of pools, with their own chunks. * The first element of the list, _M_tpools[0], can be used by any thread. @@ -1242,24 +1272,6 @@ namespace pmr return pools; } - static inline size_t - choose_block_size(size_t bytes, size_t alignment) - { - if (bytes == 0) [[unlikely]] - return alignment; - - // Use bit_ceil in case alignment is invalid (i.e. not a power of two). - size_t mask = std::__bit_ceil(alignment) - 1; - // Round up to a multiple of alignment. - size_t block_size = (bytes + mask) & ~mask; - - if (block_size >= bytes) [[likely]] - return block_size; - - // Wrapped around to zero, bytes must have been impossibly large. - return numeric_limits<size_t>::max(); - } - // Override for memory_resource::do_allocate void* synchronized_pool_resource:: diff --git a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc index 6d7434ff9106..facbf00400c9 100644 --- a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc +++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc @@ -1,4 +1,5 @@ // { dg-do run { target c++17 } } +// { dg-require-gthreads "" } // Bug 118681 - unsynchronized_pool_resource may fail to respect alignment #define RESOURCE std::pmr::synchronized_pool_resource