]> git.proxmox.com Git - rustc.git/blob - library/std/src/sys/sgx/abi/mod.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / library / std / src / sys / sgx / abi / mod.rs
1 #![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
2
3 use crate::io::Write;
4 use core::sync::atomic::{AtomicUsize, Ordering};
5
6 // runtime features
7 pub(super) mod panic;
8 mod reloc;
9
10 // library features
11 pub mod mem;
12 pub mod thread;
13 pub mod tls;
14 #[macro_use]
15 pub mod usercalls;
16
17 #[cfg(not(test))]
18 global_asm!(include_str!("entry.S"));
19
20 #[repr(C)]
21 struct EntryReturn(u64, u64);
22
23 #[cfg(not(test))]
24 #[no_mangle]
25 unsafe extern "C" fn tcs_init(secondary: bool) {
26 // Be very careful when changing this code: it runs before the binary has been
27 // relocated. Any indirect accesses to symbols will likely fail.
28 const UNINIT: usize = 0;
29 const BUSY: usize = 1;
30 const DONE: usize = 2;
31 // Three-state spin-lock
32 static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT);
33
34 if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE {
35 rtabort!("Entered secondary TCS before main TCS!")
36 }
37
38 // Try to atomically swap UNINIT with BUSY. The returned state can be:
39 match RELOC_STATE.compare_exchange(UNINIT, BUSY, Ordering::Acquire, Ordering::Acquire) {
40 // This thread just obtained the lock and other threads will observe BUSY
41 Ok(_) => {
42 reloc::relocate_elf_rela();
43 RELOC_STATE.store(DONE, Ordering::Release);
44 }
45 // We need to wait until the initialization is done.
46 Err(BUSY) => {
47 while RELOC_STATE.load(Ordering::Acquire) == BUSY {
48 core::hint::spin_loop();
49 }
50 }
51 // Initialization is done.
52 Err(DONE) => {}
53 _ => unreachable!(),
54 }
55 }
56
57 // FIXME: this item should only exist if this is linked into an executable
58 // (main function exists). If this is a library, the crate author should be
59 // able to specify this
60 #[cfg(not(test))]
61 #[no_mangle]
62 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn {
63 // FIXME: how to support TLS in library mode?
64 let tls = Box::new(tls::Tls::new());
65 let tls_guard = unsafe { tls.activate() };
66
67 if secondary {
68 let join_notifier = super::thread::Thread::entry();
69 drop(tls_guard);
70 drop(join_notifier);
71
72 EntryReturn(0, 0)
73 } else {
74 extern "C" {
75 fn main(argc: isize, argv: *const *const u8) -> isize;
76 }
77
78 // check entry is being called according to ABI
79 rtassert!(p3 == 0);
80 rtassert!(p4 == 0);
81 rtassert!(p5 == 0);
82
83 unsafe {
84 // The actual types of these arguments are `p1: *const Arg, p2:
85 // usize`. We can't currently customize the argument list of Rust's
86 // main function, so we pass these in as the standard pointer-sized
87 // values in `argc` and `argv`.
88 let ret = main(p2 as _, p1 as _);
89 exit_with_code(ret)
90 }
91 }
92 }
93
94 pub(super) fn exit_with_code(code: isize) -> ! {
95 if code != 0 {
96 if let Some(mut out) = panic::SgxPanicOutput::new() {
97 let _ = write!(out, "Exited with status code {}", code);
98 }
99 }
100 usercalls::exit(code != 0);
101 }
102
103 #[cfg(not(test))]
104 #[no_mangle]
105 extern "C" fn abort_reentry() -> ! {
106 usercalls::exit(false)
107 }