diff --git a/crates/private/tests/root-task/panicking/src/main.rs b/crates/private/tests/root-task/panicking/src/main.rs index 0a95349be..4010992c8 100644 --- a/crates/private/tests/root-task/panicking/src/main.rs +++ b/crates/private/tests/root-task/panicking/src/main.rs @@ -58,7 +58,7 @@ cfg_if::cfg_if! { assert_eq!(r.err().unwrap().inner().downcast_ref::().unwrap().as_str(), "foo"); } } else { - use panicking::FitsWithinSmallPayload; + use panicking::SmallPayload; fn whether_alloc() { let r = panicking::catch_unwind(|| { @@ -70,6 +70,6 @@ cfg_if::cfg_if! { #[derive(Copy, Clone)] struct Foo(usize); - impl FitsWithinSmallPayload for Foo {} + impl SmallPayload for Foo {} } } diff --git a/crates/sel4-microkit/src/panicking.rs b/crates/sel4-microkit/src/panicking.rs index 5b9156ac0..2694eef9d 100644 --- a/crates/sel4-microkit/src/panicking.rs +++ b/crates/sel4-microkit/src/panicking.rs @@ -9,8 +9,7 @@ use sel4_panicking::set_hook as set_outer_hook; use sel4_panicking_env::debug_println; pub use sel4_panicking::{ - catch_unwind, panic_any, ExternalPanicInfo, FitsWithinSmallPayload, PanicHook, Payload, - SmallPayloadValue, UpcastIntoPayload, + catch_unwind, panic_any, ExternalPanicInfo, PanicHook, Payload, SmallPayload, UpcastIntoPayload, }; use crate::pd_name; diff --git a/crates/sel4-panicking/src/lib.rs b/crates/sel4-panicking/src/lib.rs index 93f6bac9d..57b156c45 100644 --- a/crates/sel4-panicking/src/lib.rs +++ b/crates/sel4-panicking/src/lib.rs @@ -34,9 +34,7 @@ use payload::NoPayload; use strategy::{panic_cleanup, start_panic}; pub use hook::{set_hook, PanicHook}; -pub use payload::{FitsWithinSmallPayload, Payload, SmallPayloadValue, UpcastIntoPayload}; - -// // // +pub use payload::{Payload, SmallPayload, UpcastIntoPayload, SMALL_PAYLOAD_MAX_SIZE}; pub struct ExternalPanicInfo<'a> { payload: Payload, @@ -110,8 +108,6 @@ fn do_panic(info: ExternalPanicInfo) -> ! { } } -// // // - pub fn catch_unwind R>(f: F) -> Result { union Data { f: ManuallyDrop, diff --git a/crates/sel4-panicking/src/payload/mod.rs b/crates/sel4-panicking/src/payload/mod.rs index ae9b38f55..a97e6fa88 100644 --- a/crates/sel4-panicking/src/payload/mod.rs +++ b/crates/sel4-panicking/src/payload/mod.rs @@ -5,7 +5,6 @@ // use core::mem; -use core::slice; cfg_if::cfg_if! { if #[cfg(feature = "alloc")] { @@ -23,34 +22,26 @@ pub trait UpcastIntoPayload { fn upcast_into_payload(self) -> Payload; } -#[derive(Clone, Copy)] -pub struct SmallPayloadValue([u8; Self::SIZE]); - -impl SmallPayloadValue { - pub const SIZE: usize = 32; +pub const SMALL_PAYLOAD_MAX_SIZE: usize = 32; - pub const fn ensure_fits() { - assert!(mem::size_of::() <= Self::SIZE); - } +#[allow(dead_code)] +#[inline(always)] +const fn check_small_payload_size() { + struct Check(T); - pub fn write(val: &T) -> Self { - Self::ensure_fits::(); - let val_bytes = - unsafe { slice::from_raw_parts(val as *const T as *const u8, mem::size_of::()) }; - let mut payload_arr = [0; Self::SIZE]; - payload_arr[..val_bytes.len()].copy_from_slice(val_bytes); - Self(payload_arr) + impl Check { + const CHECK: () = assert!( + mem::size_of::() <= SMALL_PAYLOAD_MAX_SIZE, + "type is is too large to implement SmallPayload", + ); } - pub fn read(&self) -> T { - Self::ensure_fits::(); - unsafe { mem::transmute_copy(&self.0) } - } + Check::::CHECK } -pub trait FitsWithinSmallPayload {} +pub trait SmallPayload {} #[derive(Clone, Copy)] pub(crate) struct NoPayload; -impl FitsWithinSmallPayload for NoPayload {} +impl SmallPayload for NoPayload {} diff --git a/crates/sel4-panicking/src/payload/with_alloc.rs b/crates/sel4-panicking/src/payload/with_alloc.rs index 2d816aad6..c3e8258d1 100644 --- a/crates/sel4-panicking/src/payload/with_alloc.rs +++ b/crates/sel4-panicking/src/payload/with_alloc.rs @@ -13,7 +13,7 @@ use super::UpcastIntoPayload; pub struct Payload(Box); impl Payload { - pub fn new(inner: Box) -> Self { + fn new(inner: Box) -> Self { Self(inner) } diff --git a/crates/sel4-panicking/src/payload/without_alloc.rs b/crates/sel4-panicking/src/payload/without_alloc.rs index ccbc001ab..77f46b406 100644 --- a/crates/sel4-panicking/src/payload/without_alloc.rs +++ b/crates/sel4-panicking/src/payload/without_alloc.rs @@ -5,8 +5,11 @@ // use core::any::{Any, TypeId}; +use core::mem; +use core::ptr; +use core::slice; -use super::{FitsWithinSmallPayload, SmallPayloadValue, UpcastIntoPayload}; +use super::{check_small_payload_size, SmallPayload, UpcastIntoPayload, SMALL_PAYLOAD_MAX_SIZE}; pub struct Payload { type_id: TypeId, @@ -18,7 +21,7 @@ impl Payload { self.type_id } - pub fn downcast(self) -> Result { + pub fn downcast(self) -> Result { if self.type_id() == TypeId::of::() { Ok(self.value.read()) } else { @@ -27,7 +30,7 @@ impl Payload { } } -impl UpcastIntoPayload for T { +impl UpcastIntoPayload for T { fn upcast_into_payload(self) -> Payload { let type_id = self.type_id(); Payload { @@ -36,3 +39,22 @@ impl UpcastIntoPayload for T { } } } + +#[derive(Clone, Copy)] +struct SmallPayloadValue([u8; SMALL_PAYLOAD_MAX_SIZE]); + +impl SmallPayloadValue { + fn write(val: &T) -> Self { + check_small_payload_size::(); + let val_bytes = + unsafe { slice::from_raw_parts(ptr::addr_of!(*val).cast::(), mem::size_of::()) }; + let mut payload_arr = [0; SMALL_PAYLOAD_MAX_SIZE]; + payload_arr[..val_bytes.len()].copy_from_slice(val_bytes); + Self(payload_arr) + } + + fn read(&self) -> T { + check_small_payload_size::(); + unsafe { mem::transmute_copy(&self.0) } + } +}