Skip to content

Commit d26cacf

Browse files
committed
std: lazily allocate the main thread handle
#123550 elimintated the allocation of the main thread handle, but at the cost of greatly increased complexity. This PR proposes another approach: Instead of creating the main thread handle itself, the runtime simply remembers the thread ID of the main thread. The main thread handle is then only allocated when it is used, using the same lazy-initialization mechanism as for non-runtime use of `thread::current`, and the `name` method uses the thread ID to identify the main thread handle and return the correct name ("main") for it. Thereby, we also allow accessing `thread::current` before main: as the runtime no longer tries to install its own handle, this will no longer trigger an abort. Rather, the name returned from `name` will only be "main" after the runtime initialization code has run, but I think that is acceptable. I've also moved the `Thread` code into its own module, the size of `thread/mod.rs` is just getting out of hand.
1 parent 3b0cbae commit d26cacf

File tree

7 files changed

+326
-325
lines changed

7 files changed

+326
-325
lines changed

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@
365365
#![feature(std_internals)]
366366
#![feature(str_internals)]
367367
#![feature(strict_provenance_atomic_ptr)]
368+
#![feature(sync_unsafe_cell)]
368369
#![feature(ub_checks)]
369370
// tidy-alphabetical-end
370371
//

library/std/src/rt.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use core::panicking::{panic_display, panic_fmt};
2323
#[rustfmt::skip]
2424
use crate::any::Any;
2525
use crate::sync::Once;
26-
use crate::thread::{self, Thread};
26+
use crate::thread::{current_id, set_main_thread};
2727
use crate::{mem, panic, sys};
2828

2929
// Prints to the "panic output", depending on the platform this may be:
@@ -102,23 +102,10 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
102102
sys::init(argc, argv, sigpipe)
103103
};
104104

105-
// Set up the current thread handle to give it the right name.
106-
//
107-
// When code running before main uses `ReentrantLock` (for example by
108-
// using `println!`), the thread ID can become initialized before we
109-
// create this handle. Since `set_current` fails when the ID of the
110-
// handle does not match the current ID, we should attempt to use the
111-
// current thread ID here instead of unconditionally creating a new
112-
// one. Also see #130210.
113-
let thread = Thread::new_main(thread::current_id());
114-
if let Err(_thread) = thread::set_current(thread) {
115-
// `thread::current` will create a new handle if none has been set yet.
116-
// Thus, if someone uses it before main, this call will fail. That's a
117-
// bad idea though, as we then cannot set the main thread name here.
118-
//
119-
// FIXME: detect the main thread in `thread::current` and use the
120-
// correct name there.
121-
rtabort!("code running before main must not use thread::current");
105+
// Mark the current thread as main thread.
106+
// SAFETY: this is the only place and time where this is called.
107+
unsafe {
108+
set_main_thread(current_id());
122109
}
123110
}
124111

library/std/src/sys/sync/rwlock/queue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl Node {
201201
// Fall back to creating an unnamed `Thread` handle to allow locking in
202202
// TLS destructors.
203203
self.thread.get_or_init(|| {
204-
thread::try_current().unwrap_or_else(|| Thread::new_unnamed(ThreadId::new()))
204+
thread::try_current().unwrap_or_else(|| Thread::new(ThreadId::new(), None))
205205
});
206206
self.completed = AtomicBool::new(false);
207207
}

library/std/src/thread/current.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ fn init_current(current: *mut ()) -> Thread {
204204
CURRENT.set(BUSY);
205205
// If the thread ID was initialized already, use it.
206206
let id = id::get_or_init();
207-
let thread = Thread::new_unnamed(id);
207+
let thread = Thread::new(id, None);
208208

209209
// Make sure that `crate::rt::thread_cleanup` will be run, which will
210210
// call `drop_current`.

0 commit comments

Comments
 (0)