Skip to content

Commit e237e37

Browse files
committed
[libc] Fix riscv32 Block assertion failure on #117815
1 parent 5a735a2 commit e237e37

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

libc/src/__support/block.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,17 @@ class Block {
227227
*new (&next()->prev_) size_t = outer_size();
228228
}
229229

230-
/// Marks this block as the last one in the chain. Makes next() return
231-
/// nullptr.
232-
LIBC_INLINE void mark_last() { next_ |= LAST_MASK; }
233-
234-
LIBC_INLINE Block(size_t outer_size) : next_(outer_size) {
235-
LIBC_ASSERT(outer_size % alignof(max_align_t) == 0 &&
236-
"block sizes must be aligned");
230+
LIBC_INLINE Block(size_t outer_size, bool is_last) : next_(outer_size) {
231+
// Last blocks are not usable, so they need not have sizes aligned to
232+
// max_align_t. Their lower bits must still be free, so they must be aligned
233+
// to Block.
234+
LIBC_ASSERT(
235+
outer_size % (is_last ? alignof(Block) : alignof(max_align_t)) == 0 &&
236+
"block sizes must be aligned");
237237
LIBC_ASSERT(is_usable_space_aligned(alignof(max_align_t)) &&
238238
"usable space must be aligned to a multiple of max_align_t");
239+
if (is_last)
240+
next_ |= LAST_MASK;
239241
}
240242

241243
LIBC_INLINE bool is_usable_space_aligned(size_t alignment) const {
@@ -325,7 +327,13 @@ class Block {
325327
LIBC_ASSERT(reinterpret_cast<uintptr_t>(bytes.data()) % alignof(Block) ==
326328
0 &&
327329
"block start must be suitably aligned");
328-
return ::new (bytes.data()) Block(bytes.size());
330+
return ::new (bytes.data()) Block(bytes.size(), /*is_last=*/false);
331+
}
332+
333+
LIBC_INLINE static void make_last_block(cpp::byte *start) {
334+
LIBC_ASSERT(reinterpret_cast<uintptr_t>(start) % alignof(Block) == 0 &&
335+
"block start must be suitably aligned");
336+
::new (start) Block(sizeof(Block), /*is_last=*/true);
329337
}
330338

331339
/// Offset from this block to the previous block. 0 if this is the first
@@ -353,7 +361,7 @@ class Block {
353361
static constexpr size_t PREV_FIELD_SIZE = sizeof(prev_);
354362
};
355363

356-
static_assert(alignof(max_align_t) >= 4,
364+
static_assert(alignof(Block) >= 4,
357365
"at least 2 bits must be available in block sizes for flags");
358366

359367
LIBC_INLINE
@@ -380,9 +388,8 @@ optional<Block *> Block::init(ByteSpan region) {
380388
auto *last_start_ptr = reinterpret_cast<cpp::byte *>(last_start);
381389
Block *block =
382390
as_block({reinterpret_cast<cpp::byte *>(block_start), last_start_ptr});
383-
Block *last = as_block({last_start_ptr, sizeof(Block)});
391+
make_last_block(last_start_ptr);
384392
block->mark_free();
385-
last->mark_last();
386393
return block;
387394
}
388395

0 commit comments

Comments
 (0)