Simplify dtor registration for HermitCore by using a list of destructors

The implementation is similiar to macOS solution doesn't
depend on additional OS support
This commit is contained in:
Stefan Lankes 2020-04-05 13:37:04 +02:00
parent 7b657d340d
commit 935683bd9c
4 changed files with 49 additions and 45 deletions

View File

@ -1,4 +1,36 @@
#![cfg(target_thread_local)]
#![unstable(feature = "thread_local_internals", issue = "none")]
pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
// Simplify dtor registration by using a list of destructors.
// The this solution works like the implementation of macOS and
// doesn't additional OS support
use crate::cell::Cell;
use crate::ptr;
#[thread_local]
static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
if DTORS.get().is_null() {
let v: Box<List> = box Vec::new();
DTORS.set(Box::into_raw(v));
}
let list: &mut List = &mut *DTORS.get();
list.push((t, dtor));
}
// every thread call this function to run through all possible destructors
pub unsafe fn run_dtors() {
let mut ptr = DTORS.replace(ptr::null_mut());
while !ptr.is_null() {
let list = Box::from_raw(ptr);
for (ptr, dtor) in list.into_iter() {
dtor(ptr);
}
ptr = DTORS.replace(ptr::null_mut());
}
}

View File

@ -103,6 +103,7 @@ pub fn init() {
argv: *const *const c_char,
env: *const *const c_char,
) -> ! {
use crate::sys::hermit::fast_thread_local::run_dtors;
extern "C" {
fn main(argc: isize, argv: *const *const c_char) -> i32;
}
@ -112,6 +113,7 @@ pub fn init() {
let result = main(argc as isize, argv);
run_dtors();
abi::exit(result);
}

View File

@ -5,6 +5,7 @@
use crate::io;
use crate::mem;
use crate::sys::hermit::abi;
use crate::sys::hermit::fast_thread_local::run_dtors;
use crate::time::Duration;
use core::u32;
@ -70,6 +71,9 @@ extern "C" fn thread_start(main: usize) {
unsafe {
// Finally, let's run some code.
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
// run all destructors
run_dtors();
}
}
}

View File

@ -1,60 +1,26 @@
#![allow(dead_code)] // not used on all platforms
use crate::collections::BTreeMap;
use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys_common::mutex::Mutex;
pub type Key = usize;
type Dtor = unsafe extern "C" fn(*mut u8);
static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
static KEYS_LOCK: Mutex = Mutex::new();
#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
if KEYS.is_null() {
KEYS = Box::into_raw(Box::new(BTreeMap::new()));
}
&mut *KEYS
}
unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
if LOCALS.is_null() {
LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
}
&mut *LOCALS
#[inline]
pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
panic!("should not be used on the wasm target");
}
#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
let _guard = KEYS_LOCK.lock();
keys().insert(key, dtor);
key
pub unsafe fn set(_key: Key, _value: *mut u8) {
panic!("should not be used on the wasm target");
}
#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
if let Some(&entry) = locals().get(&key) { entry } else { ptr::null_mut() }
pub unsafe fn get(_key: Key) -> *mut u8 {
panic!("should not be used on the wasm target");
}
#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
locals().insert(key, value);
}
#[inline]
pub unsafe fn destroy(key: Key) {
keys().remove(&key);
pub unsafe fn destroy(_key: Key) {
panic!("should not be used on the wasm target");
}
#[inline]
pub fn requires_synchronized_create() -> bool {
false
panic!("should not be used on the wasm target");
}