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:
parent
7b657d340d
commit
935683bd9c
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user