--- a/library/std/src/sys/thread_local/destructors/list.rs
+++ b/library/std/src/sys/thread_local/destructors/list.rs
@@ -1,9 +1,25 @@
 use crate::cell::RefCell;
 use crate::sys::thread_local::guard;
 
+#[cfg(not(target_enforce_emulated_tls))]
 #[thread_local]
 static DTORS: RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>> = RefCell::new(Vec::new());
 
+#[cfg(target_enforce_emulated_tls)]
+use crate::sys::thread_local::key::StaticKey;
+
+#[cfg(target_enforce_emulated_tls)]
+static DTORS: StaticKey<RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>>> =
+    StaticKey::new(None);
+
+#[cfg(target_enforce_emulated_tls)]
+fn dtors() -> &'static RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>> {
+    unsafe {
+        DTORS.get()
+            .unwrap_or_else(|| rtabort!("DTORS not initialized"))
+    }
+}
+
 pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     let Ok(mut dtors) = DTORS.try_borrow_mut() else {
         // This point can only be reached if the global allocator calls this
@@ -12,6 +28,12 @@
         rtabort!("the global allocator may not use TLS with destructors");
     };
 
+    #[cfg(target_enforce_emulated_tls)]
+    if dtors.is_empty() {
+        // Initialize on first use
+        unsafe { DTORS.initialize(RefCell::new(Vec::new())) };
+    }
+
     guard::enable();
 
     dtors.push((t, dtor));
@@ -25,6 +47,17 @@
 /// May only be run on thread exit to guarantee that there are no live references
 /// to TLS variables while they are destroyed.
 pub unsafe fn run() {
+    #[cfg(target_enforce_emulated_tls)]
+    {
+        // For emulated TLS, check if DTORS is initialized
+        let Some(dtors_ref) = (unsafe { DTORS.get() }) else {
+            return; // Nothing to clean up
+        };
+        run_impl(dtors_ref);
+        return;
+    }
+
+    #[cfg(not(target_enforce_emulated_tls))]
     loop {
         let mut dtors = DTORS.borrow_mut();
         match dtors.pop() {
@@ -42,3 +75,23 @@
         }
     }
 }
+
+#[cfg(target_enforce_emulated_tls)]
+unsafe fn run_impl(dtors_ref: &RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>>) {
+    loop {
+        let mut dtors = dtors_ref.borrow_mut();
+        match dtors.pop() {
+            Some((t, dtor)) => {
+                drop(dtors);
+                unsafe {
+                    dtor(t);
+                }
+            }
+            None => {
+                // Free the list memory.
+                *dtors = Vec::new();
+                break;
+            }
+        }
+    }
+}
