1use crate::platform::types::{c_int, c_void};
2use alloc::vec::Vec;
3use core::cell::RefCell;
4use spin::Mutex;
5
6#[derive(Clone, Copy)]
7struct CxaAtExitFunc {
8 func: extern "C" fn(*mut c_void),
9 arg: usize,
10 dso: usize,
11}
12
13#[derive(Clone, Copy)]
14struct CxaThreadAtExitFunc {
15 func: extern "C" fn(*mut c_void),
16 obj: *mut c_void,
17 dso: *mut c_void,
18}
19
20static CXA_ATEXIT_FUNCS: Mutex<Vec<Option<CxaAtExitFunc>>> = Mutex::new(Vec::new());
21#[thread_local]
22static DTORS: RefCell<Vec<CxaThreadAtExitFunc>> = RefCell::new(Vec::new());
23
24#[unsafe(no_mangle)]
25pub unsafe extern "C" fn __cxa_atexit(
26 func: Option<extern "C" fn(*mut c_void)>,
27 arg: *mut c_void,
28 dso: *mut c_void,
29) -> c_int {
30 let Some(func) = func else {
31 return 0;
32 };
33
34 let entry = CxaAtExitFunc {
35 func,
36 arg: arg as usize,
37 dso: dso as usize,
38 };
39
40 let mut funcs = CXA_ATEXIT_FUNCS.lock();
41
42 for slot in funcs.iter_mut() {
43 if slot.is_none() {
44 *slot = Some(entry);
45 return 0;
46 }
47 }
48
49 funcs.push(Some(entry));
51 0
52}
53
54#[unsafe(no_mangle)]
55pub unsafe extern "C" fn __cxa_finalize(dso: *mut c_void) {
56 let mut funcs = CXA_ATEXIT_FUNCS.lock();
57
58 let dso_usize = dso as usize;
59
60 for slot in funcs.iter_mut().rev() {
61 if let Some(entry) = slot.as_ref()
62 && (dso.is_null() || entry.dso == dso_usize)
63 && let Some(entry_to_run) = slot.take()
64 {
65 (entry_to_run.func)(entry_to_run.arg as *mut c_void);
66 }
67 }
68
69 if dso.is_null() {
71 funcs.clear();
72 } else {
73 funcs.retain(|opt| opt.is_some());
74 }
75}
76
77#[unsafe(no_mangle)]
78pub unsafe extern "C" fn __cxa_thread_atexit_impl(
79 func: extern "C" fn(*mut c_void),
80 obj: *mut c_void,
81 dso: *mut c_void,
82) {
83 let entry = CxaThreadAtExitFunc { func, obj, dso };
84 DTORS.borrow_mut().push(entry);
85}
86
87pub unsafe fn __cxa_thread_finalize() {
89 let mut dtors = DTORS.borrow_mut();
90 while let Some(entry) = dtors.pop() {
91 (entry.func)(entry.obj);
92 }
93}
94
95#[unsafe(no_mangle)]
96pub unsafe extern "C" fn _ITM_deregisterTMCloneTable(_ptr: *mut c_void) {
97 }
99
100#[unsafe(no_mangle)]
101pub unsafe extern "C" fn _ITM_registerTMCloneTable(_ptr: *mut c_void, _len: usize) {
102 }