Skip to content

Commit 935683b

Browse files
committed
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
1 parent 7b657d3 commit 935683b

File tree

4 files changed

+48
-44
lines changed

4 files changed

+48
-44
lines changed
+33-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
11
#![cfg(target_thread_local)]
22
#![unstable(feature = "thread_local_internals", issue = "none")]
33

4-
pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
4+
// Simplify dtor registration by using a list of destructors.
5+
// The this solution works like the implementation of macOS and
6+
// doesn't additional OS support
7+
8+
use crate::cell::Cell;
9+
use crate::ptr;
10+
11+
#[thread_local]
12+
static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
13+
14+
type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
15+
16+
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
17+
if DTORS.get().is_null() {
18+
let v: Box<List> = box Vec::new();
19+
DTORS.set(Box::into_raw(v));
20+
}
21+
22+
let list: &mut List = &mut *DTORS.get();
23+
list.push((t, dtor));
24+
}
25+
26+
// every thread call this function to run through all possible destructors
27+
pub unsafe fn run_dtors() {
28+
let mut ptr = DTORS.replace(ptr::null_mut());
29+
while !ptr.is_null() {
30+
let list = Box::from_raw(ptr);
31+
for (ptr, dtor) in list.into_iter() {
32+
dtor(ptr);
33+
}
34+
ptr = DTORS.replace(ptr::null_mut());
35+
}
36+
}

src/libstd/sys/hermit/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub unsafe extern "C" fn runtime_entry(
103103
argv: *const *const c_char,
104104
env: *const *const c_char,
105105
) -> ! {
106+
use crate::sys::hermit::fast_thread_local::run_dtors;
106107
extern "C" {
107108
fn main(argc: isize, argv: *const *const c_char) -> i32;
108109
}
@@ -112,6 +113,7 @@ pub unsafe extern "C" fn runtime_entry(
112113

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

116+
run_dtors();
115117
abi::exit(result);
116118
}
117119

src/libstd/sys/hermit/thread.rs

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::fmt;
55
use crate::io;
66
use crate::mem;
77
use crate::sys::hermit::abi;
8+
use crate::sys::hermit::fast_thread_local::run_dtors;
89
use crate::time::Duration;
910
use core::u32;
1011

@@ -70,6 +71,9 @@ impl Thread {
7071
unsafe {
7172
// Finally, let's run some code.
7273
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
74+
75+
// run all destructors
76+
run_dtors();
7377
}
7478
}
7579
}

src/libstd/sys/hermit/thread_local.rs

+9-43
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,26 @@
1-
#![allow(dead_code)] // not used on all platforms
2-
3-
use crate::collections::BTreeMap;
4-
use crate::ptr;
5-
use crate::sync::atomic::{AtomicUsize, Ordering};
6-
use crate::sys_common::mutex::Mutex;
7-
81
pub type Key = usize;
92

10-
type Dtor = unsafe extern "C" fn(*mut u8);
11-
12-
static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
13-
14-
static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
15-
static KEYS_LOCK: Mutex = Mutex::new();
16-
17-
#[thread_local]
18-
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
19-
20-
unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
21-
if KEYS.is_null() {
22-
KEYS = Box::into_raw(Box::new(BTreeMap::new()));
23-
}
24-
&mut *KEYS
25-
}
26-
27-
unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
28-
if LOCALS.is_null() {
29-
LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
30-
}
31-
&mut *LOCALS
32-
}
33-
343
#[inline]
35-
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
36-
let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
37-
let _guard = KEYS_LOCK.lock();
38-
keys().insert(key, dtor);
39-
key
4+
pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
5+
panic!("should not be used on the wasm target");
406
}
417

428
#[inline]
43-
pub unsafe fn get(key: Key) -> *mut u8 {
44-
if let Some(&entry) = locals().get(&key) { entry } else { ptr::null_mut() }
9+
pub unsafe fn set(_key: Key, _value: *mut u8) {
10+
panic!("should not be used on the wasm target");
4511
}
4612

4713
#[inline]
48-
pub unsafe fn set(key: Key, value: *mut u8) {
49-
locals().insert(key, value);
14+
pub unsafe fn get(_key: Key) -> *mut u8 {
15+
panic!("should not be used on the wasm target");
5016
}
5117

5218
#[inline]
53-
pub unsafe fn destroy(key: Key) {
54-
keys().remove(&key);
19+
pub unsafe fn destroy(_key: Key) {
20+
panic!("should not be used on the wasm target");
5521
}
5622

5723
#[inline]
5824
pub fn requires_synchronized_create() -> bool {
59-
false
25+
panic!("should not be used on the wasm target");
6026
}

0 commit comments

Comments
 (0)