• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 mod sync_bitset;
2 
3 use self::sync_bitset::*;
4 use crate::cell::Cell;
5 use crate::mem;
6 use crate::num::NonZeroUsize;
7 use crate::ptr;
8 use crate::sync::atomic::{AtomicUsize, Ordering};
9 
10 #[cfg(target_pointer_width = "64")]
11 const USIZE_BITS: usize = 64;
12 const TLS_KEYS: usize = 128; // Same as POSIX minimum
13 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
14 
15 #[cfg_attr(test, linkage = "available_externally")]
16 #[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
17 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
18 macro_rules! dup {
19     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
20     (() $($val:tt)*) => ([$($val),*])
21 }
22 #[cfg_attr(test, linkage = "available_externally")]
23 #[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
24 static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
25 
26 extern "C" {
get_tls_ptr() -> *const u827     fn get_tls_ptr() -> *const u8;
set_tls_ptr(tls: *const u8)28     fn set_tls_ptr(tls: *const u8);
29 }
30 
31 #[derive(Copy, Clone)]
32 #[repr(C)]
33 pub struct Key(NonZeroUsize);
34 
35 impl Key {
to_index(self) -> usize36     fn to_index(self) -> usize {
37         self.0.get() - 1
38     }
39 
from_index(index: usize) -> Self40     fn from_index(index: usize) -> Self {
41         Key(NonZeroUsize::new(index + 1).unwrap())
42     }
43 
as_usize(self) -> usize44     pub fn as_usize(self) -> usize {
45         self.0.get()
46     }
47 
from_usize(index: usize) -> Self48     pub fn from_usize(index: usize) -> Self {
49         Key(NonZeroUsize::new(index).unwrap())
50     }
51 }
52 
53 #[repr(C)]
54 pub struct Tls {
55     data: [Cell<*mut u8>; TLS_KEYS],
56 }
57 
58 pub struct ActiveTls<'a> {
59     tls: &'a Tls,
60 }
61 
62 impl<'a> Drop for ActiveTls<'a> {
drop(&mut self)63     fn drop(&mut self) {
64         let value_with_destructor = |key: usize| {
65             let ptr = TLS_DESTRUCTOR[key].load(Ordering::Relaxed);
66             unsafe { mem::transmute::<_, Option<unsafe extern "C" fn(*mut u8)>>(ptr) }
67                 .map(|dtor| (&self.tls.data[key], dtor))
68         };
69 
70         let mut any_non_null_dtor = true;
71         while any_non_null_dtor {
72             any_non_null_dtor = false;
73             for (value, dtor) in TLS_KEY_IN_USE.iter().filter_map(&value_with_destructor) {
74                 let value = value.replace(ptr::null_mut());
75                 if !value.is_null() {
76                     any_non_null_dtor = true;
77                     unsafe { dtor(value) }
78                 }
79             }
80         }
81     }
82 }
83 
84 impl Tls {
new() -> Tls85     pub fn new() -> Tls {
86         Tls { data: dup!((* * * * * * *) (Cell::new(ptr::null_mut()))) }
87     }
88 
activate(&self) -> ActiveTls<'_>89     pub unsafe fn activate(&self) -> ActiveTls<'_> {
90         // FIXME: Needs safety information. See entry.S for `set_tls_ptr` definition.
91         unsafe { set_tls_ptr(self as *const Tls as _) };
92         ActiveTls { tls: self }
93     }
94 
95     #[allow(unused)]
activate_persistent(self: Box<Self>)96     pub unsafe fn activate_persistent(self: Box<Self>) {
97         // FIXME: Needs safety information. See entry.S for `set_tls_ptr` definition.
98         unsafe { set_tls_ptr((&*self) as *const Tls as _) };
99         mem::forget(self);
100     }
101 
current<'a>() -> &'a Tls102     unsafe fn current<'a>() -> &'a Tls {
103         // FIXME: Needs safety information. See entry.S for `set_tls_ptr` definition.
104         unsafe { &*(get_tls_ptr() as *const Tls) }
105     }
106 
create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key107     pub fn create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
108         let index = if let Some(index) = TLS_KEY_IN_USE.set() {
109             index
110         } else {
111             rtabort!("TLS limit exceeded")
112         };
113         TLS_DESTRUCTOR[index].store(dtor.map_or(0, |f| f as usize), Ordering::Relaxed);
114         unsafe { Self::current() }.data[index].set(ptr::null_mut());
115         Key::from_index(index)
116     }
117 
set(key: Key, value: *mut u8)118     pub fn set(key: Key, value: *mut u8) {
119         let index = key.to_index();
120         rtassert!(TLS_KEY_IN_USE.get(index));
121         unsafe { Self::current() }.data[index].set(value);
122     }
123 
get(key: Key) -> *mut u8124     pub fn get(key: Key) -> *mut u8 {
125         let index = key.to_index();
126         rtassert!(TLS_KEY_IN_USE.get(index));
127         unsafe { Self::current() }.data[index].get()
128     }
129 
destroy(key: Key)130     pub fn destroy(key: Key) {
131         TLS_KEY_IN_USE.clear(key.to_index());
132     }
133 }
134