]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/solid/thread_local_dtor.rs
Rollup merge of #105265 - aDotInTheVoid:sum-product-on-unimplemented, r=estebank
[rust.git] / library / std / src / sys / solid / thread_local_dtor.rs
1 #![cfg(target_thread_local)]
2 #![unstable(feature = "thread_local_internals", issue = "none")]
3
4 // Simplify dtor registration by using a list of destructors.
5
6 use super::{abi, itron::task};
7 use crate::cell::Cell;
8 use crate::ptr;
9
10 #[thread_local]
11 static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
12
13 type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
14
15 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
16     if DTORS.get().is_null() {
17         let tid = task::current_task_id_aborting();
18         let v: Box<List> = box Vec::new();
19         DTORS.set(Box::into_raw(v));
20
21         // Register `tls_dtor` to make sure the TLS destructors are called
22         // for tasks created by other means than `std::thread`
23         unsafe { abi::SOLID_TLS_AddDestructor(tid as i32, tls_dtor) };
24     }
25
26     let list: &mut List = unsafe { &mut *DTORS.get() };
27     list.push((t, dtor));
28 }
29
30 pub unsafe fn run_dtors() {
31     let ptr = DTORS.get();
32     if !ptr.is_null() {
33         // Swap the destructor list, call all registered destructors,
34         // and repeat this until the list becomes permanently empty.
35         while let Some(list) = Some(crate::mem::replace(unsafe { &mut *ptr }, Vec::new()))
36             .filter(|list| !list.is_empty())
37         {
38             for (ptr, dtor) in list.into_iter() {
39                 unsafe { dtor(ptr) };
40             }
41         }
42
43         // Drop the destructor list
44         unsafe { Box::from_raw(DTORS.replace(ptr::null_mut())) };
45     }
46 }
47
48 unsafe extern "C" fn tls_dtor(_unused: *mut u8) {
49     unsafe { run_dtors() };
50 }