Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify dtor registration for HermitCore by using a list of destructors #70808

Merged
merged 1 commit into from
Apr 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/libstd/sys/hermit/fast_thread_local.rs
Original file line number Diff line number Diff line change
@@ -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());
}
}
2 changes: 2 additions & 0 deletions src/libstd/sys/hermit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub unsafe extern "C" fn runtime_entry(
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;
}
Expand All @@ -112,6 +113,7 @@ pub unsafe extern "C" fn runtime_entry(

let result = main(argc as isize, argv);

run_dtors();
abi::exit(result);
}

Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sys/hermit/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::fmt;
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;

Expand Down Expand Up @@ -70,6 +71,9 @@ impl Thread {
unsafe {
// Finally, let's run some code.
Box::from_raw(main as *mut Box<dyn FnOnce()>)();

// run all destructors
run_dtors();
}
}
}
Expand Down
52 changes: 9 additions & 43 deletions src/libstd/sys/hermit/thread_local.rs
Original file line number Diff line number Diff line change
@@ -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<Dtor>) -> Key {
let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
let _guard = KEYS_LOCK.lock();
keys().insert(key, dtor);
key
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 get(key: Key) -> *mut u8 {
if let Some(&entry) = locals().get(&key) { entry } else { ptr::null_mut() }
pub unsafe fn set(_key: Key, _value: *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);
pub unsafe fn get(_key: Key) -> *mut u8 {
panic!("should not be used on the wasm target");
}

#[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");
}