]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/wasm/thread_local_atomics.rs
Simplify SaveHandler trait
[rust.git] / src / libstd / sys / wasm / thread_local_atomics.rs
1 use crate::sys::thread;
2 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
3
4 const MAX_KEYS: usize = 128;
5 static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
6
7 struct ThreadControlBlock {
8     keys: [*mut u8; MAX_KEYS],
9 }
10
11 impl ThreadControlBlock {
12     fn new() -> ThreadControlBlock {
13         ThreadControlBlock {
14             keys: [core::ptr::null_mut(); MAX_KEYS],
15         }
16     }
17
18     fn get() -> *mut ThreadControlBlock {
19         let ptr = thread::tcb_get();
20         if !ptr.is_null() {
21             return ptr as *mut ThreadControlBlock
22         }
23         let tcb = Box::into_raw(Box::new(ThreadControlBlock::new()));
24         thread::tcb_set(tcb as *mut u8);
25         tcb
26     }
27 }
28
29 pub type Key = usize;
30
31 pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
32     drop(dtor); // FIXME: need to figure out how to hook thread exit to run this
33     let key = NEXT_KEY.fetch_add(1, SeqCst);
34     if key >= MAX_KEYS {
35         NEXT_KEY.store(MAX_KEYS, SeqCst);
36         panic!("cannot allocate space for more TLS keys");
37     }
38     // offset by 1 so we never hand out 0. This is currently required by
39     // `sys_common/thread_local.rs` where it can't cope with keys of value 0
40     // because it messes up the atomic management.
41     return key + 1
42 }
43
44 pub unsafe fn set(key: Key, value: *mut u8) {
45     (*ThreadControlBlock::get()).keys[key - 1] = value;
46 }
47
48 pub unsafe fn get(key: Key) -> *mut u8 {
49     (*ThreadControlBlock::get()).keys[key - 1]
50 }
51
52 pub unsafe fn destroy(_key: Key) {
53     // FIXME: should implement this somehow, this isn't typically called but it
54     // can be called if two threads race to initialize a TLS slot and one ends
55     // up not being needed.
56 }
57
58 #[inline]
59 pub fn requires_synchronized_create() -> bool {
60     false
61 }