fix pthread-based tls on apple targets
This commit is contained in:
parent
75530e9f72
commit
e41cce03a0
6 changed files with 76 additions and 1 deletions
|
@ -138,6 +138,7 @@ pub(crate) mod key {
|
|||
not(target_family = "wasm"),
|
||||
target_family = "unix",
|
||||
),
|
||||
all(not(target_thread_local), target_vendor = "apple"),
|
||||
target_os = "teeos",
|
||||
all(target_os = "wasi", target_env = "p1", target_feature = "atomics"),
|
||||
))] {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(cfg_target_thread_local)]
|
||||
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod tests;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::thread::{self, Builder, LocalKey};
|
||||
use std::thread::{self, LocalKey};
|
||||
use std::thread_local;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
@ -345,8 +345,27 @@ fn join_orders_after_tls_destructors() {
|
|||
}
|
||||
|
||||
// Test that thread::current is still available in TLS destructors.
|
||||
//
|
||||
// The test won't currently work without target_thread_local, aka with slow tls.
|
||||
// The runtime tries very hard to drop last the TLS variable that keeps the information about the
|
||||
// current thread, by using several tricks like deffering the drop to a later round of TLS destruction.
|
||||
// However, this only seems to work with fast tls.
|
||||
//
|
||||
// With slow TLS, it seems that multiple libc implementations will just set the value to null the first
|
||||
// time they encounter it, regardless of it having a destructor or not. This means that trying to
|
||||
// retrieve it later in a drop impl of another TLS variable will not work.
|
||||
//
|
||||
// ** Apple libc: https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread_tsd.c#L293
|
||||
// Sets the variable to null if it has a destructor and the value is not null. However, all variables
|
||||
// created with pthread_key_create are marked as having a destructor, even if the fn ptr called with
|
||||
// it is null.
|
||||
// ** glibc: https://github.com/bminor/glibc/blob/e5893e6349541d871e8a25120bca014551d13ff5/nptl/nptl_deallocate_tsd.c#L59
|
||||
// ** musl: https://github.com/kraj/musl/blob/1880359b54ff7dd9f5016002bfdae4b136007dde/src/thread/pthread_key_create.c#L87
|
||||
#[cfg(target_thread_local)]
|
||||
#[test]
|
||||
fn thread_current_in_dtor() {
|
||||
use std::thread::Builder;
|
||||
|
||||
// Go through one round of TLS destruction first.
|
||||
struct Defer;
|
||||
impl Drop for Defer {
|
||||
|
|
37
tests/run-make/apple-slow-tls/rmake.rs
Normal file
37
tests/run-make/apple-slow-tls/rmake.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
//! Test if compilation with has-thread-local=false works, and if the output
|
||||
//! has indeed no fast TLS variables.
|
||||
|
||||
//@ only-apple
|
||||
|
||||
use run_make_support::serde_json::{self, Value};
|
||||
use run_make_support::{cargo, llvm_nm, rfs, rustc};
|
||||
|
||||
fn main() {
|
||||
let output =
|
||||
rustc().print("target-spec-json").args(["-Z", "unstable-options"]).run().stdout_utf8();
|
||||
|
||||
let mut target_json: Value = serde_json::from_str(&output).unwrap();
|
||||
let has_thread_local = &mut target_json["has-thread-local"];
|
||||
assert!(matches!(has_thread_local, Value::Bool(true)), "{:?}", has_thread_local);
|
||||
*has_thread_local = Value::Bool(false);
|
||||
|
||||
let out_path = "t.json";
|
||||
rfs::write(out_path, serde_json::to_string(&target_json).unwrap());
|
||||
|
||||
cargo()
|
||||
.args([
|
||||
"b",
|
||||
"--manifest-path",
|
||||
"tls_test/Cargo.toml",
|
||||
"--target",
|
||||
"t.json",
|
||||
"-Zbuild-std=std,core,panic_abort",
|
||||
])
|
||||
.run();
|
||||
|
||||
// If a binary has any fast TLS variables, it should also contain the symbols
|
||||
// __tlv_bootstrap and __tlv_atexit. We don't want them.
|
||||
let output = llvm_nm().arg("tls_test/target/t/debug/tls_test").run().stdout_utf8();
|
||||
assert!(!output.contains("_tlv_bootstrap"));
|
||||
assert!(!output.contains("_tlv_atexit"));
|
||||
}
|
6
tests/run-make/apple-slow-tls/tls_test/Cargo.toml
Normal file
6
tests/run-make/apple-slow-tls/tls_test/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "tls_test"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
10
tests/run-make/apple-slow-tls/tls_test/src/main.rs
Normal file
10
tests/run-make/apple-slow-tls/tls_test/src/main.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
fn main() {
|
||||
thread_local! {
|
||||
static S: RefCell<String> = RefCell::default();
|
||||
}
|
||||
|
||||
S.with(|x| *x.borrow_mut() = "pika pika".to_string());
|
||||
S.with(|x| println!("{}", x.borrow()));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue