| 1 | //! Store the ID of the main thread. |
| 2 | //! |
| 3 | //! The thread handle for the main thread is created lazily, and this might even |
| 4 | //! happen pre-main. Since not every platform has a way to identify the main |
| 5 | //! thread when that happens – macOS's `pthread_main_np` function being a notable |
| 6 | //! exception – we cannot assign it the right name right then. Instead, in our |
| 7 | //! runtime startup code, we remember the thread ID of the main thread (through |
| 8 | //! this modules `set` function) and use it to identify the main thread from then |
| 9 | //! on. This works reliably and has the additional advantage that we can report |
| 10 | //! the right thread name on main even after the thread handle has been destroyed. |
| 11 | //! Note however that this also means that the name reported in pre-main functions |
| 12 | //! will be incorrect, but that's just something we have to live with. |
| 13 | |
| 14 | cfg_select! { |
| 15 | target_has_atomic = "64" => { |
| 16 | use super::id::ThreadId; |
| 17 | use crate::sync::atomic::{Atomic, AtomicU64}; |
| 18 | use crate::sync::atomic::Ordering::Relaxed; |
| 19 | |
| 20 | static MAIN: Atomic<u64> = AtomicU64::new(0); |
| 21 | |
| 22 | pub(super) fn get() -> Option<ThreadId> { |
| 23 | ThreadId::from_u64(MAIN.load(Relaxed)) |
| 24 | } |
| 25 | |
| 26 | /// # Safety |
| 27 | /// May only be called once. |
| 28 | pub(crate) unsafe fn set(id: ThreadId) { |
| 29 | MAIN.store(id.as_u64().get(), Relaxed) |
| 30 | } |
| 31 | } |
| 32 | _ => { |
| 33 | use super::id::ThreadId; |
| 34 | use crate::mem::MaybeUninit; |
| 35 | use crate::sync::atomic::{Atomic, AtomicBool}; |
| 36 | use crate::sync::atomic::Ordering::{Acquire, Release}; |
| 37 | |
| 38 | static INIT: Atomic<bool> = AtomicBool::new(false); |
| 39 | static mut MAIN: MaybeUninit<ThreadId> = MaybeUninit::uninit(); |
| 40 | |
| 41 | pub(super) fn get() -> Option<ThreadId> { |
| 42 | if INIT.load(Acquire) { |
| 43 | Some(unsafe { MAIN.assume_init() }) |
| 44 | } else { |
| 45 | None |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | /// # Safety |
| 50 | /// May only be called once. |
| 51 | pub(crate) unsafe fn set(id: ThreadId) { |
| 52 | unsafe { MAIN = MaybeUninit::new(id) }; |
| 53 | INIT.store(true, Release); |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | |