From 6d63012a62eff7b8ab46c5eda565e0aed5e1d003 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 7 Nov 2024 09:51:52 -0800 Subject: [PATCH] Initialize channel `Block`s directly on the heap The channel's `Block::new` was causing a stack overflow because it held 32 item slots, instantiated on the stack before moving to `Box::new`. The 32x multiplier made modestly-large item sizes untenable. That block is now initialized directly on the heap. Fixes #102246 --- std/src/sync/mpmc/list.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/std/src/sync/mpmc/list.rs b/std/src/sync/mpmc/list.rs index 88a8c75f7c8b9..523e6d2f3bb37 100644 --- a/std/src/sync/mpmc/list.rs +++ b/std/src/sync/mpmc/list.rs @@ -63,14 +63,14 @@ struct Block { impl Block { /// Creates an empty block. - fn new() -> Block { + fn new() -> Box> { // SAFETY: This is safe because: // [1] `Block::next` (AtomicPtr) may be safely zero initialized. // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. // [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it // holds a MaybeUninit. // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + unsafe { Box::new_zeroed().assume_init() } } /// Waits until the next pointer is set. @@ -199,13 +199,13 @@ impl Channel { // If we're going to have to install the next block, allocate it in advance in order to // make the wait for other threads as short as possible. if offset + 1 == BLOCK_CAP && next_block.is_none() { - next_block = Some(Box::new(Block::::new())); + next_block = Some(Block::::new()); } // If this is the first message to be sent into the channel, we need to allocate the // first block and install it. if block.is_null() { - let new = Box::into_raw(Box::new(Block::::new())); + let new = Box::into_raw(Block::::new()); if self .tail