summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/solid/thread_local_dtor.rs
blob: bad14bb37f720e50707898944ca5e88212e358c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#![cfg(target_thread_local)]
#![unstable(feature = "thread_local_internals", issue = "none")]

// Simplify dtor registration by using a list of destructors.

use super::{abi, itron::task};
use crate::cell::Cell;
use crate::mem;

#[thread_local]
static REGISTERED: Cell<bool> = Cell::new(false);

#[thread_local]
static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();

pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
    if !REGISTERED.get() {
        let tid = task::current_task_id_aborting();
        // Register `tls_dtor` to make sure the TLS destructors are called
        // for tasks created by other means than `std::thread`
        unsafe { abi::SOLID_TLS_AddDestructor(tid as i32, tls_dtor) };
        REGISTERED.set(true);
    }

    let list = unsafe { &mut DTORS };
    list.push((t, dtor));
}

pub unsafe fn run_dtors() {
    let mut list = mem::take(unsafe { &mut DTORS });
    while !list.is_empty() {
        for (ptr, dtor) in list {
            unsafe { dtor(ptr) };
        }

        list = mem::take(unsafe { &mut DTORS });
    }
}

unsafe extern "C" fn tls_dtor(_unused: *mut u8) {
    unsafe { run_dtors() };
}