Skip to content

Commit 2c28cc4

Browse files
committed
add comments explaining main thread identification
1 parent 1d25252 commit 2c28cc4

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

library/std/src/thread/current.rs

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ where
156156
{
157157
let current = CURRENT.get();
158158
if current > DESTROYED {
159+
// SAFETY: `Arc` does not contain interior mutability, so it does not
160+
// matter that the address of the handle might be different depending
161+
// on where this is called.
159162
unsafe {
160163
let current = ManuallyDrop::new(Thread::from_raw(current));
161164
f(Some(&current))

library/std/src/thread/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,18 @@ mod thread_name_string {
12861286

12871287
use thread_name_string::ThreadNameString;
12881288

1289+
/// Store the ID of the main thread.
1290+
///
1291+
/// The thread handle for the main thread is created lazily, and this might even
1292+
/// happen pre-main. Since not every platform has a way to identify the main
1293+
/// thread when that happens – macOS's `pthread_main_np` function being a notable
1294+
/// exception – we cannot assign it the right name right then. Instead, in our
1295+
/// runtime startup code, we remember the thread ID of the main thread (through
1296+
/// this modules `set` function) and use it to identify the main thread from then
1297+
/// on. This works reliably and has the additional advantage that we can report
1298+
/// the right thread name on main even after the thread handle has been destroyed.
1299+
/// Note however that this also means that the name reported in pre-main functions
1300+
/// will be incorrect, but that's just something we have to live with.
12891301
pub(crate) mod main_thread {
12901302
cfg_if::cfg_if! {
12911303
if #[cfg(target_has_atomic = "64")] {
@@ -1331,21 +1343,35 @@ pub(crate) mod main_thread {
13311343
}
13321344
}
13331345

1346+
/// Run a function with the current thread's name.
1347+
///
1348+
/// Modulo thread local accesses, this function is safe to call from signal
1349+
/// handlers and in similar circumstances where allocations are not possible.
13341350
pub(crate) fn with_current_name<F, R>(f: F) -> R
13351351
where
13361352
F: FnOnce(Option<&str>) -> R,
13371353
{
13381354
try_with_current(|thread| {
13391355
if let Some(thread) = thread {
1356+
// If there is a current thread handle, try to use the name stored
1357+
// there.
13401358
if let Some(name) = &thread.inner.name {
13411359
return f(Some(name.as_str()));
13421360
} else if Some(thread.inner.id) == main_thread::get() {
1361+
// The main thread doesn't store its name in the handle, we must
1362+
// identify it through its ID. Since we already have the `Thread`,
1363+
// we can retrieve the ID from it instead of going through another
1364+
// thread local.
13431365
return f(Some("main"));
13441366
}
13451367
} else if let Some(main) = main_thread::get()
13461368
&& let Some(id) = current::id::get()
13471369
&& id == main
13481370
{
1371+
// The main thread doesn't always have a thread handle, we must
1372+
// identify it through its ID instead. The checks are ordered so
1373+
// that the current ID is only loaded if it is actually needed,
1374+
// since loading it from TLS might need multiple expensive accesses.
13491375
return f(Some("main"));
13501376
}
13511377

0 commit comments

Comments
 (0)