dynlink/compartment/
tls.rs1use std::{alloc::Layout, ptr::NonNull};
2
3use tracing::{debug, trace};
4
5use super::Compartment;
6use crate::{
7 tls::{TlsInfo, TlsModId, TlsModule, TlsRegion},
8 DynlinkError, DynlinkErrorKind,
9};
10
11impl Compartment {
12 pub(crate) fn insert(&mut self, tm: TlsModule) -> TlsModId {
13 let prev_gen = self.tls_gen;
14 self.tls_gen += 1;
15 let prev_info = self
16 .tls_info
17 .remove(&prev_gen)
18 .unwrap_or_else(|| TlsInfo::new(self.tls_gen));
19 let mut next = prev_info.clone_to_new_gen(self.tls_gen);
20 let id = next.insert(tm);
21 self.tls_info.insert(self.tls_gen, next);
22 id
23 }
24
25 pub fn advance_tls_generation(&mut self) -> u64 {
27 let tng = self.tls_gen + 1;
28 let initial = if let Some(prev) = self.tls_info.get(&self.tls_gen) {
29 prev.clone_to_new_gen(tng)
30 } else {
31 TlsInfo::new(tng)
32 };
33 self.tls_info.insert(tng, initial);
34 tng
35 }
36
37 pub fn build_tls_region<T>(
39 &mut self,
40 tcb: T,
41 alloc: impl FnOnce(Layout) -> Option<NonNull<u8>>,
42 ) -> Result<TlsRegion, DynlinkError> {
43 let tls_info = self.tls_info.get(&self.tls_gen).ok_or_else(|| {
44 DynlinkError::new(DynlinkErrorKind::NoTLSInfo {
45 library: self.name.clone(),
46 })
47 })?;
48 let alloc_layout = tls_info
49 .allocation_layout::<T>()
50 .map_err(DynlinkErrorKind::from)?;
51 let base = alloc(alloc_layout).ok_or_else(|| DynlinkErrorKind::FailedToAllocate {
53 comp: self.name.clone(),
54 layout: alloc_layout,
55 })?;
56 debug!(
57 "{}: building static TLS region (size: {}, align: {}) -> {:p}",
58 self,
59 alloc_layout.size(),
60 alloc_layout.align(),
61 base
62 );
63
64 let tls_info = self.tls_info.get(&self.tls_gen).ok_or_else(|| {
65 DynlinkError::new(DynlinkErrorKind::NoTLSInfo {
66 library: self.name.clone(),
67 })
68 })?;
69 let tls_region = tls_info.allocate(self, base, tcb);
70 trace!("{}: static TLS region: {:?}", self, tls_region);
71 tls_region
72 }
73}