blob: c70f2ecc04e3a9caff6af4a1d49d045c4e7cf1ff [file] [log] [blame]
#![deny(unsafe_op_in_unsafe_fn)]
use crate::sync::Once;
use crate::sys;
use crate::sys_common::thread_info;
use crate::thread::Thread;
// One-time runtime initialization.
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
unsafe {
sys::init(argc, argv);
let main_guard = sys::thread::guard::init();
// Next, set up the current Thread with the guard information we just
// created. Note that this isn't necessary in general for new threads,
// but we just do this to name the main thread and to give it correct
// info about the stack bounds.
let thread = Thread::new(Some("main".to_owned()));
thread_info::set(main_guard, thread);
}
}
// One-time runtime cleanup.
// Runs after `main` or at program exit.
// NOTE: this is not guaranteed to run, for example when the program aborts.
#[cfg_attr(test, allow(dead_code))]
pub fn cleanup() {
static CLEANUP: Once = Once::new();
CLEANUP.call_once(|| unsafe {
// Flush stdout and disable buffering.
crate::io::cleanup();
// SAFETY: Only called once during runtime cleanup.
sys::cleanup();
});
}
macro_rules! rtabort {
($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*)))
}
macro_rules! rtassert {
($e:expr) => {
if !$e {
rtabort!(concat!("assertion failed: ", stringify!($e)));
}
};
}
#[allow(unused_macros)] // not used on all platforms
macro_rules! rtunwrap {
($ok:ident, $e:expr) => {
match $e {
$ok(v) => v,
ref err => {
let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
}
}
};
}