// Copyright 2024 The percore Authors. // This project is dual-licensed under Apache 2.0 and MIT terms. // See LICENSE-APACHE and LICENSE-MIT for details. #[cfg(target_arch = "aarch64")] mod aarch64; #[cfg(target_arch = "aarch64")] use aarch64::{mask, restore}; use core::marker::PhantomData; /// Runs the given function with exceptions masked. /// /// Only IRQs, FIQs and SErrors can be masked. Synchronous exceptions cannot be masked and so may /// still occur. #[cfg(target_arch = "aarch64")] pub fn exception_free(f: impl FnOnce(ExceptionFree<'_>) -> T) -> T { // Mask all exceptions and save previous mask state. let prev = mask(); // SAFETY: We just masked exceptions. let token = unsafe { ExceptionFree::new() }; let result = f(token); // SAFETY: `token` has been dropped by now, as its lifetime prevents `f` from storing it. unsafe { // Restore previous exception mask state. restore(prev); } result } /// A token proving that exceptions are currently masked. /// /// Note that synchronous exceptions cannot be masked and so may still occur. #[derive(Clone, Copy, Debug)] pub struct ExceptionFree<'cs> { _private: PhantomData<&'cs ()>, } impl<'cs> ExceptionFree<'cs> { /// Constructs a new instance of `ExceptionFree`, promising that exceptions will remain masked /// for at least its lifetime. /// /// This usually should not be called directly; instead use [`exception_free`]. /// /// # Safety /// /// `ExceptionFree` must only be constructed while exceptions are masked, and they must not be /// unmasked until after it is dropped. pub unsafe fn new() -> Self { Self { _private: PhantomData, } } }