1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use core::sync::atomic::{AtomicUsize, Ordering};
25 global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
28 unsafe extern "C" fn tcs_init(secondary: bool) {
29 // Be very careful when changing this code: it runs before the binary has been
30 // relocated. Any indirect accesses to symbols will likely fail.
31 const UNINIT: usize = 0;
32 const BUSY: usize = 1;
33 const DONE: usize = 2;
34 // Three-state spin-lock
35 static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT);
37 if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE {
38 panic::panic_msg("Entered secondary TCS before main TCS!")
41 // Try to atomically swap UNINIT with BUSY. The returned state can be:
42 match RELOC_STATE.compare_and_swap(UNINIT, BUSY, Ordering::Acquire) {
43 // This thread just obtained the lock and other threads will observe BUSY
45 reloc::relocate_elf_rela();
46 RELOC_STATE.store(DONE, Ordering::Release);
48 // We need to wait until the initialization is done.
49 BUSY => while RELOC_STATE.load(Ordering::Acquire) == BUSY {
50 ::core::arch::x86_64::_mm_pause()
52 // Initialization is done.
58 // FIXME: this item should only exist if this is linked into an executable
59 // (main function exists). If this is a library, the crate author should be
60 // able to specify this
62 #[allow(unreachable_code)]
63 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
64 // FIXME: how to support TLS in library mode?
65 let tls = Box::new(tls::Tls::new());
66 let _tls_guard = unsafe { tls.activate() };
69 unimplemented!("thread entrypoint");
74 fn main(argc: isize, argv: *const *const u8) -> isize;
77 // check entry is being called according to ABI
83 // The actual types of these arguments are `p1: *const Arg, p2:
84 // usize`. We can't currently customize the argument list of Rust's
85 // main function, so we pass these in as the standard pointer-sized
86 // values in `argc` and `argv`.
87 let ret = main(p2 as _, p1 as _);
93 pub(super) fn exit_with_code(code: isize) -> ! {
95 if let Some(mut out) = panic::SgxPanicOutput::new() {
96 let _ = write!(out, "Exited with status code {}", code);
99 unsafe { usercalls::raw::exit(code != 0) };