diff options
| author | Sebastian Urban <surban@surban.net> | 2024-11-23 21:28:09 +0100 |
|---|---|---|
| committer | Sebastian Urban <surban@surban.net> | 2024-11-25 19:57:57 +0100 |
| commit | ec5f41a9531947cd87d7daca124e2e7b55f23b35 (patch) | |
| tree | 7eaa6aa9d7b75b03d237c49c7633df300f3c9cf6 | |
| parent | 7db7489f9bc274cb60c4956bfa56de0185eb1b9b (diff) | |
| download | rust-ec5f41a9531947cd87d7daca124e2e7b55f23b35.tar.gz rust-ec5f41a9531947cd87d7daca124e2e7b55f23b35.zip | |
Run TLS destructors for wasm32-wasip1-threads
The target has support for pthreads and allows registration of TLS destructors.
| -rw-r--r-- | library/std/src/sys/thread_local/guard/wasi.rs | 71 | ||||
| -rw-r--r-- | library/std/src/sys/thread_local/mod.rs | 3 |
2 files changed, 74 insertions, 0 deletions
diff --git a/library/std/src/sys/thread_local/guard/wasi.rs b/library/std/src/sys/thread_local/guard/wasi.rs new file mode 100644 index 00000000000..dfd1f126aa0 --- /dev/null +++ b/library/std/src/sys/thread_local/guard/wasi.rs @@ -0,0 +1,71 @@ +//! wasm32-wasip1 has pthreads support. + +use crate::cell::Cell; +use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sys::thread_local::destructors; +use crate::{ffi, ptr}; + +// Add a few symbols not in upstream `libc` just yet. +mod libc { + pub use libc::*; + + use crate::ffi; + + #[allow(non_camel_case_types)] + pub type pthread_key_t = ffi::c_uint; + + extern "C" { + pub fn pthread_key_create( + key: *mut pthread_key_t, + destructor: unsafe extern "C" fn(*mut ffi::c_void), + ) -> ffi::c_int; + + pub fn pthread_setspecific(key: pthread_key_t, value: *const ffi::c_void) -> ffi::c_int; + } +} + +pub fn enable() { + enable_main(); + enable_thread(); +} + +fn enable_main() { + static REGISTERED: AtomicBool = AtomicBool::new(false); + + if !REGISTERED.swap(true, Ordering::AcqRel) { + unsafe { + assert_eq!(libc::atexit(run_main_dtors), 0); + } + } + + extern "C" fn run_main_dtors() { + unsafe { + destructors::run(); + crate::rt::thread_cleanup(); + } + } +} + +fn enable_thread() { + #[thread_local] + static REGISTERED: Cell<bool> = Cell::new(false); + + if !REGISTERED.replace(true) { + unsafe { + let mut key: libc::pthread_key_t = 0; + assert_eq!(libc::pthread_key_create(&mut key, run_thread_dtors), 0); + + // We must set the value to a non-NULL pointer value so that + // the destructor is run on thread exit. The pointer is only + // passed to run_dtors and never dereferenced. + assert_eq!(libc::pthread_setspecific(key, ptr::without_provenance(1)), 0); + } + } + + extern "C" fn run_thread_dtors(_: *mut ffi::c_void) { + unsafe { + destructors::run(); + crate::rt::thread_cleanup(); + } + } +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 31d3b439060..042f0f76c9a 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -85,6 +85,9 @@ pub(crate) mod guard { } else if #[cfg(target_os = "windows")] { mod windows; pub(crate) use windows::enable; + } else if #[cfg(all(target_os = "wasi"))] { + mod wasi; + pub(crate) use wasi::enable; } else if #[cfg(any( target_family = "wasm", target_os = "uefi", |
