std: move thread::current
TLS variable out of thread_info
This commit is contained in:
parent
5b9d7ab558
commit
7668418101
@ -21,7 +21,6 @@ use crate::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use crate::sync::{PoisonError, RwLock};
|
use crate::sync::{PoisonError, RwLock};
|
||||||
use crate::sys::stdio::panic_output;
|
use crate::sys::stdio::panic_output;
|
||||||
use crate::sys_common::backtrace;
|
use crate::sys_common::backtrace;
|
||||||
use crate::sys_common::thread_info;
|
|
||||||
use crate::thread;
|
use crate::thread;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
@ -256,7 +255,7 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||||||
None => "Box<dyn Any>",
|
None => "Box<dyn Any>",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let thread = thread_info::current_thread();
|
let thread = thread::try_current();
|
||||||
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
||||||
|
|
||||||
let write = |err: &mut dyn crate::io::Write| {
|
let write = |err: &mut dyn crate::io::Write| {
|
||||||
|
@ -24,8 +24,7 @@ pub use core::panicking::{panic_display, panic_fmt};
|
|||||||
|
|
||||||
use crate::sync::Once;
|
use crate::sync::Once;
|
||||||
use crate::sys;
|
use crate::sys;
|
||||||
use crate::sys_common::thread_info;
|
use crate::thread::{self, Thread};
|
||||||
use crate::thread::Thread;
|
|
||||||
|
|
||||||
// Prints to the "panic output", depending on the platform this may be:
|
// Prints to the "panic output", depending on the platform this may be:
|
||||||
// - the standard error output
|
// - the standard error output
|
||||||
@ -96,13 +95,12 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
|||||||
unsafe {
|
unsafe {
|
||||||
sys::init(argc, argv, sigpipe);
|
sys::init(argc, argv, sigpipe);
|
||||||
|
|
||||||
let main_guard = sys::thread::guard::init();
|
|
||||||
// Next, set up the current Thread with the guard information we just
|
// Next, set up the current Thread with the guard information we just
|
||||||
// created. Note that this isn't necessary in general for new threads,
|
// created. Note that this isn't necessary in general for new threads,
|
||||||
// but we just do this to name the main thread and to give it correct
|
// but we just do this to name the main thread and to give it correct
|
||||||
// info about the stack bounds.
|
// info about the stack bounds.
|
||||||
let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main"))));
|
let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main"))));
|
||||||
thread_info::set(main_guard, thread);
|
thread::set_current(thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,13 +104,3 @@ impl Thread {
|
|||||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||||
unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) }
|
unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -312,16 +312,6 @@ impl Drop for Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Terminate and delete the specified task.
|
/// Terminate and delete the specified task.
|
||||||
///
|
///
|
||||||
/// This function will abort if `deleted_task` refers to the calling task.
|
/// This function will abort if `deleted_task` refers to the calling task.
|
||||||
|
@ -149,13 +149,3 @@ impl Thread {
|
|||||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -151,18 +151,6 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// stub
|
|
||||||
pub mod guard {
|
|
||||||
use crate::ops::Range;
|
|
||||||
pub type Guard = Range<usize>;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
|
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
|
||||||
libc::PTHREAD_STACK_MIN.try_into().expect("Infallible")
|
libc::PTHREAD_STACK_MIN.try_into().expect("Infallible")
|
||||||
}
|
}
|
||||||
|
@ -52,13 +52,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
|||||||
// UEFI is single threaded
|
// UEFI is single threaded
|
||||||
Ok(NonZero::new(1).unwrap())
|
Ok(NonZero::new(1).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -729,17 +729,6 @@ mod cgroups {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
use crate::ops::Range;
|
|
||||||
pub type Guard = Range<usize>;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
|
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
|
||||||
// PTHREAD_STACK_MIN plus bytes needed for thread-local storage.
|
// PTHREAD_STACK_MIN plus bytes needed for thread-local storage.
|
||||||
// We need that information to avoid blowing up when a small stack
|
// We need that information to avoid blowing up when a small stack
|
||||||
|
@ -38,13 +38,3 @@ impl Thread {
|
|||||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -193,13 +193,3 @@ impl Thread {
|
|||||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -144,14 +144,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
|||||||
cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
|
cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, allow(dead_code))]
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -140,13 +140,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
|||||||
// We're unicore right now.
|
// We're unicore right now.
|
||||||
Ok(unsafe { NonZero::new_unchecked(1) })
|
Ok(unsafe { NonZero::new_unchecked(1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod guard {
|
|
||||||
pub type Guard = !;
|
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -115,8 +115,7 @@ use crate::sync::atomic::{
|
|||||||
AtomicBool, AtomicPtr,
|
AtomicBool, AtomicPtr,
|
||||||
Ordering::{AcqRel, Acquire, Relaxed, Release},
|
Ordering::{AcqRel, Acquire, Relaxed, Release},
|
||||||
};
|
};
|
||||||
use crate::sys_common::thread_info;
|
use crate::thread::{self, Thread};
|
||||||
use crate::thread::Thread;
|
|
||||||
|
|
||||||
// Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the
|
// Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the
|
||||||
// locking operation will be retried.
|
// locking operation will be retried.
|
||||||
@ -203,8 +202,7 @@ impl Node {
|
|||||||
fn prepare(&mut self) {
|
fn prepare(&mut self) {
|
||||||
// Fall back to creating an unnamed `Thread` handle to allow locking in
|
// Fall back to creating an unnamed `Thread` handle to allow locking in
|
||||||
// TLS destructors.
|
// TLS destructors.
|
||||||
self.thread
|
self.thread.get_or_init(|| thread::try_current().unwrap_or_else(|| Thread::new(None)));
|
||||||
.get_or_init(|| thread_info::current_thread().unwrap_or_else(|| Thread::new(None)));
|
|
||||||
self.completed = AtomicBool::new(false);
|
self.completed = AtomicBool::new(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ pub mod io;
|
|||||||
pub mod lazy_box;
|
pub mod lazy_box;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod thread_info;
|
|
||||||
pub mod thread_local_dtor;
|
pub mod thread_local_dtor;
|
||||||
pub mod thread_parking;
|
pub mod thread_parking;
|
||||||
pub mod wstr;
|
pub mod wstr;
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
|
|
||||||
|
|
||||||
use crate::cell::OnceCell;
|
|
||||||
use crate::sys;
|
|
||||||
use crate::sys::thread::guard::Guard;
|
|
||||||
use crate::thread::Thread;
|
|
||||||
|
|
||||||
struct ThreadInfo {
|
|
||||||
stack_guard: OnceCell<Guard>,
|
|
||||||
thread: OnceCell<Thread>,
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
static THREAD_INFO: ThreadInfo = const { ThreadInfo {
|
|
||||||
stack_guard: OnceCell::new(),
|
|
||||||
thread: OnceCell::new()
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ThreadInfo {
|
|
||||||
fn with<R, F>(f: F) -> Option<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
|
|
||||||
{
|
|
||||||
THREAD_INFO
|
|
||||||
.try_with(move |thread_info| {
|
|
||||||
let thread =
|
|
||||||
thread_info.thread.get_or_init(|| Thread::new(sys::thread::Thread::get_name()));
|
|
||||||
f(thread, &thread_info.stack_guard)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_thread() -> Option<Thread> {
|
|
||||||
ThreadInfo::with(|thread, _| thread.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stack_guard() -> Option<Guard> {
|
|
||||||
ThreadInfo::with(|_, guard| guard.get().cloned()).flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set new thread info, panicking if it has already been initialized
|
|
||||||
#[allow(unreachable_code, unreachable_patterns)] // some platforms don't use stack_guard
|
|
||||||
pub fn set(stack_guard: Option<Guard>, thread: Thread) {
|
|
||||||
THREAD_INFO.with(move |thread_info| {
|
|
||||||
rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
|
|
||||||
if let Some(guard) = stack_guard {
|
|
||||||
thread_info.stack_guard.set(guard).unwrap();
|
|
||||||
}
|
|
||||||
thread_info.thread.set(thread).unwrap();
|
|
||||||
});
|
|
||||||
}
|
|
@ -159,7 +159,7 @@
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::Any;
|
||||||
use crate::cell::UnsafeCell;
|
use crate::cell::{OnceCell, UnsafeCell};
|
||||||
use crate::ffi::{CStr, CString};
|
use crate::ffi::{CStr, CString};
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
@ -174,7 +174,6 @@ use crate::str;
|
|||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
use crate::sys::thread as imp;
|
use crate::sys::thread as imp;
|
||||||
use crate::sys_common::thread;
|
use crate::sys_common::thread;
|
||||||
use crate::sys_common::thread_info;
|
|
||||||
use crate::sys_common::thread_parking::Parker;
|
use crate::sys_common::thread_parking::Parker;
|
||||||
use crate::sys_common::{AsInner, IntoInner};
|
use crate::sys_common::{AsInner, IntoInner};
|
||||||
use crate::time::{Duration, Instant};
|
use crate::time::{Duration, Instant};
|
||||||
@ -518,12 +517,8 @@ impl Builder {
|
|||||||
|
|
||||||
crate::io::set_output_capture(output_capture);
|
crate::io::set_output_capture(output_capture);
|
||||||
|
|
||||||
// SAFETY: we constructed `f` initialized.
|
|
||||||
let f = f.into_inner();
|
let f = f.into_inner();
|
||||||
// SAFETY: the stack guard passed is the one for the current thread.
|
set_current(their_thread);
|
||||||
// This means the current thread's stack and the new thread's stack
|
|
||||||
// are properly set and protected from each other.
|
|
||||||
thread_info::set(unsafe { imp::guard::current() }, their_thread);
|
|
||||||
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||||
crate::sys_common::backtrace::__rust_begin_short_backtrace(f)
|
crate::sys_common::backtrace::__rust_begin_short_backtrace(f)
|
||||||
}));
|
}));
|
||||||
@ -683,6 +678,27 @@ where
|
|||||||
Builder::new().spawn(f).expect("failed to spawn thread")
|
Builder::new().spawn(f).expect("failed to spawn thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the thread handle for the current thread.
|
||||||
|
///
|
||||||
|
/// Panics if the handle has been set already or when called from a TLS destructor.
|
||||||
|
pub(crate) fn set_current(thread: Thread) {
|
||||||
|
CURRENT.with(|current| current.set(thread).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a handle to the thread that invokes it.
|
||||||
|
///
|
||||||
|
/// In contrast to the public `current` function, this will not panic if called
|
||||||
|
/// from inside a TLS destructor.
|
||||||
|
pub(crate) fn try_current() -> Option<Thread> {
|
||||||
|
CURRENT
|
||||||
|
.try_with(|current| current.get_or_init(|| Thread::new(imp::Thread::get_name())).clone())
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a handle to the thread that invokes it.
|
/// Gets a handle to the thread that invokes it.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -705,7 +721,7 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn current() -> Thread {
|
pub fn current() -> Thread {
|
||||||
thread_info::current_thread().expect(
|
try_current().expect(
|
||||||
"use of std::thread::current() is not possible \
|
"use of std::thread::current() is not possible \
|
||||||
after the thread's local data has been destroyed",
|
after the thread's local data has been destroyed",
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user