[gcc r16-2123] libstdc++: Fix memory_resource.cc bootstrap failure for non-gthreads targets
Jonathan Wakely
redi@gcc.gnu.org
Wed Jul 9 10:03:38 GMT 2025
https://gcc.gnu.org/g:7a878ba615c2c51ea9cf89142033c5e1ad71795e
commit r16-2123-g7a878ba615c2c51ea9cf89142033c5e1ad71795e
Author: Jonathan Wakely <jwakely@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
More information about the Libstdc++-cvs
mailing list