Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2c5b0f8

Browse files
committed
Remove last rt::init allocation for thread info
1 parent d8d5732 commit 2c5b0f8

File tree

2 files changed

+83
-40
lines changed

2 files changed

+83
-40
lines changed

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@
354354
#![feature(str_internals)]
355355
#![feature(strict_provenance)]
356356
#![feature(strict_provenance_atomic_ptr)]
357+
#![feature(sync_unsafe_cell)]
357358
#![feature(ub_checks)]
358359
// tidy-alphabetical-end
359360
//

library/std/src/thread/mod.rs

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,14 @@
159159
mod tests;
160160

161161
use crate::any::Any;
162+
use crate::cell::SyncUnsafeCell;
162163
use crate::cell::{OnceCell, UnsafeCell};
163164
use crate::env;
164165
use crate::ffi::{CStr, CString};
165166
use crate::fmt;
166167
use crate::io;
167168
use crate::marker::PhantomData;
169+
use crate::mem::MaybeUninit;
168170
use crate::mem::{self, forget};
169171
use crate::num::NonZero;
170172
use crate::panic;
@@ -530,7 +532,7 @@ impl Builder {
530532

531533
let f = MaybeDangling::new(f);
532534
let main = move || {
533-
if let Some(name) = their_thread.cname() {
535+
if let Some(name) = their_thread.0.name() {
534536
imp::Thread::set_name(name);
535537
}
536538

@@ -1168,7 +1170,7 @@ pub fn park_timeout(dur: Duration) {
11681170
let guard = PanicGuard;
11691171
// SAFETY: park_timeout is called on the parker owned by this thread.
11701172
unsafe {
1171-
current().inner.as_ref().parker().park_timeout(dur);
1173+
current().0.parker().park_timeout(dur);
11721174
}
11731175
// No panic occurred, do not abort.
11741176
forget(guard);
@@ -1207,7 +1209,12 @@ pub fn park_timeout(dur: Duration) {
12071209
pub struct ThreadId(NonZero<u64>);
12081210

12091211
impl ThreadId {
1210-
// Generate a new unique thread ID.
1212+
/// Generate a new unique thread ID.
1213+
///
1214+
/// The current implementation starts at 2 and increments from there.
1215+
///
1216+
/// This is as `1` is the value for the main thread, so std::thread::Thread does not
1217+
/// have to store this value when creating the main thread's information.
12111218
fn new() -> ThreadId {
12121219
#[cold]
12131220
fn exhausted() -> ! {
@@ -1218,7 +1225,7 @@ impl ThreadId {
12181225
if #[cfg(target_has_atomic = "64")] {
12191226
use crate::sync::atomic::AtomicU64;
12201227

1221-
static COUNTER: AtomicU64 = AtomicU64::new(0);
1228+
static COUNTER: AtomicU64 = AtomicU64::new(1);
12221229

12231230
let mut last = COUNTER.load(Ordering::Relaxed);
12241231
loop {
@@ -1234,7 +1241,7 @@ impl ThreadId {
12341241
} else {
12351242
use crate::sync::{Mutex, PoisonError};
12361243

1237-
static COUNTER: Mutex<u64> = Mutex::new(0);
1244+
static COUNTER: Mutex<u64> = Mutex::new(1);
12381245

12391246
let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
12401247
let Some(id) = counter.checked_add(1) else {
@@ -1251,6 +1258,11 @@ impl ThreadId {
12511258
}
12521259
}
12531260

1261+
/// Creates a ThreadId with the ID of the main thread.
1262+
fn new_main() -> Self {
1263+
Self(NonZero::<u64>::MIN)
1264+
}
1265+
12541266
/// This returns a numeric identifier for the thread identified by this
12551267
/// `ThreadId`.
12561268
///
@@ -1270,23 +1282,54 @@ impl ThreadId {
12701282
// Thread
12711283
////////////////////////////////////////////////////////////////////////////////
12721284

1273-
/// The internal representation of a `Thread`'s name.
1274-
enum ThreadName {
1275-
Main,
1276-
Other(CString),
1277-
Unnamed,
1278-
}
1285+
/// The parker for the main thread. This avoids having to allocate an Arc in `fn main() {}`.
1286+
static MAIN_PARKER: SyncUnsafeCell<MaybeUninit<Parker>> =
1287+
SyncUnsafeCell::new(MaybeUninit::uninit());
12791288

1280-
/// The internal representation of a `Thread` handle
1281-
struct Inner {
1282-
name: ThreadName, // Guaranteed to be UTF-8
1289+
/// The internal representation of a `Thread` that is not the main thread.
1290+
struct OtherInner {
1291+
name: Option<CString>, // Guaranteed to be UTF-8
12831292
id: ThreadId,
12841293
parker: Parker,
12851294
}
12861295

1296+
/// The internal representation of a `Thread` handle.
1297+
#[derive(Clone)]
1298+
enum Inner {
1299+
Main,
1300+
Other(Pin<Arc<OtherInner>>),
1301+
}
1302+
12871303
impl Inner {
1288-
fn parker(self: Pin<&Self>) -> Pin<&Parker> {
1289-
unsafe { Pin::map_unchecked(self, |inner| &inner.parker) }
1304+
fn id(&self) -> ThreadId {
1305+
match self {
1306+
Self::Main => ThreadId::new_main(),
1307+
Self::Other(other) => other.id,
1308+
}
1309+
}
1310+
1311+
fn name(&self) -> Option<&CStr> {
1312+
match self {
1313+
Self::Main => Some(c"main"),
1314+
Self::Other(other) => other.name.as_deref(),
1315+
}
1316+
}
1317+
1318+
fn parker(&self) -> Pin<&Parker> {
1319+
match self {
1320+
Self::Main => {
1321+
// Safety: MAIN_PARKER only ever has a mutable reference when Inner::Main is initialised.
1322+
let static_ref: &'static MaybeUninit<Parker> = unsafe { &*MAIN_PARKER.get() };
1323+
1324+
// Safety: MAIN_PARKER is initialised when Inner::Main is initialised.
1325+
let parker_ref = unsafe { static_ref.assume_init_ref() };
1326+
1327+
Pin::static_ref(parker_ref)
1328+
}
1329+
Self::Other(inner) => unsafe {
1330+
Pin::map_unchecked(inner.as_ref(), |inner| &inner.parker)
1331+
},
1332+
}
12901333
}
12911334
}
12921335

@@ -1310,46 +1353,53 @@ impl Inner {
13101353
/// docs of [`Builder`] and [`spawn`] for more details.
13111354
///
13121355
/// [`thread::current`]: current
1313-
pub struct Thread {
1314-
inner: Pin<Arc<Inner>>,
1315-
}
1356+
pub struct Thread(Inner);
13161357

13171358
impl Thread {
13181359
/// Used only internally to construct a thread object without spawning.
13191360
///
13201361
/// # Safety
13211362
/// `name` must be valid UTF-8.
13221363
pub(crate) unsafe fn new(name: CString) -> Thread {
1323-
unsafe { Self::new_inner(ThreadName::Other(name)) }
1364+
unsafe { Self::new_inner(Some(name)) }
13241365
}
13251366

13261367
pub(crate) fn new_unnamed() -> Thread {
1327-
unsafe { Self::new_inner(ThreadName::Unnamed) }
1368+
unsafe { Self::new_inner(None) }
13281369
}
13291370

1330-
// Used in runtime to construct main thread
1331-
pub(crate) fn new_main() -> Thread {
1332-
unsafe { Self::new_inner(ThreadName::Main) }
1371+
/// Used in runtime to construct main thread
1372+
///
1373+
/// # Safety
1374+
///
1375+
/// This must only ever be called once, and must be called on the main thread.
1376+
pub(crate) unsafe fn new_main() -> Thread {
1377+
// Safety: Caller responsible for holding the mutable invariant and
1378+
// Parker::new_in_place does not read from the uninit value.
1379+
unsafe { Parker::new_in_place(MAIN_PARKER.get().cast()) }
1380+
1381+
Self(Inner::Main)
13331382
}
13341383

13351384
/// # Safety
1336-
/// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
1337-
unsafe fn new_inner(name: ThreadName) -> Thread {
1385+
///
1386+
/// If `name` is `Some(_)`, the contained string must be valid UTF-8.
1387+
unsafe fn new_inner(name: Option<CString>) -> Thread {
13381388
// We have to use `unsafe` here to construct the `Parker` in-place,
13391389
// which is required for the UNIX implementation.
13401390
//
13411391
// SAFETY: We pin the Arc immediately after creation, so its address never
13421392
// changes.
13431393
let inner = unsafe {
1344-
let mut arc = Arc::<Inner>::new_uninit();
1394+
let mut arc = Arc::<OtherInner>::new_uninit();
13451395
let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr();
13461396
addr_of_mut!((*ptr).name).write(name);
13471397
addr_of_mut!((*ptr).id).write(ThreadId::new());
13481398
Parker::new_in_place(addr_of_mut!((*ptr).parker));
13491399
Pin::new_unchecked(arc.assume_init())
13501400
};
13511401

1352-
Thread { inner }
1402+
Self(Inner::Other(inner))
13531403
}
13541404

13551405
/// Like the public [`park`], but callable on any handle. This is used to
@@ -1358,7 +1408,7 @@ impl Thread {
13581408
/// # Safety
13591409
/// May only be called from the thread to which this handle belongs.
13601410
pub(crate) unsafe fn park(&self) {
1361-
unsafe { self.inner.as_ref().parker().park() }
1411+
unsafe { self.0.parker().park() }
13621412
}
13631413

13641414
/// Atomically makes the handle's token available if it is not already.
@@ -1394,7 +1444,7 @@ impl Thread {
13941444
#[stable(feature = "rust1", since = "1.0.0")]
13951445
#[inline]
13961446
pub fn unpark(&self) {
1397-
self.inner.as_ref().parker().unpark();
1447+
self.0.parker().unpark();
13981448
}
13991449

14001450
/// Gets the thread's unique identifier.
@@ -1414,7 +1464,7 @@ impl Thread {
14141464
#[stable(feature = "thread_id", since = "1.19.0")]
14151465
#[must_use]
14161466
pub fn id(&self) -> ThreadId {
1417-
self.inner.id
1467+
self.0.id()
14181468
}
14191469

14201470
/// Gets the thread's name.
@@ -1457,15 +1507,7 @@ impl Thread {
14571507
#[stable(feature = "rust1", since = "1.0.0")]
14581508
#[must_use]
14591509
pub fn name(&self) -> Option<&str> {
1460-
self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) })
1461-
}
1462-
1463-
fn cname(&self) -> Option<&CStr> {
1464-
match &self.inner.name {
1465-
ThreadName::Main => Some(c"main"),
1466-
ThreadName::Other(other) => Some(&other),
1467-
ThreadName::Unnamed => None,
1468-
}
1510+
self.0.name().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) })
14691511
}
14701512
}
14711513

0 commit comments

Comments
 (0)