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

Reply via email to