mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Adjust AnyFrameMeta
safety conditions
This commit is contained in:
parent
0d36375dfa
commit
0c028a7d8c
@ -449,16 +449,8 @@ impl<M> Link<M> {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: The size and alignment of `Link<M>` must be within the limits.
|
||||
// Also, if `M` is typed, `Link<M>` must not be untyped.
|
||||
//
|
||||
// FIXME: We would appreciate constant trait bounds very much, just like:
|
||||
// ```
|
||||
// Assert<{ core::mem::size_of::<Link<M>>() < FRAME_METADATA_MAX_SIZE }>: IsTrue,
|
||||
// Assert<{ core::mem::align_of::<Link<M>>() <= FRAME_METADATA_MAX_ALIGN }>: IsTrue,
|
||||
// ```
|
||||
// But due to the broken implementation of `generic_const_exprs` we can't do that.
|
||||
// It works for `M` that is declared inside OSTD but not for outside types.
|
||||
// SAFETY: If `M::on_drop` reads the page using the provided `VmReader`,
|
||||
// the safety is upheld by the one who implements `AnyFrameMeta` for `M`.
|
||||
unsafe impl<M> AnyFrameMeta for Link<M>
|
||||
where
|
||||
M: AnyFrameMeta,
|
||||
|
@ -134,19 +134,18 @@ const_assert_eq!(size_of::<MetaSlot>(), META_SLOT_SIZE);
|
||||
/// this frame, the `on_drop` method will be called. The `on_drop`
|
||||
/// method is called with the physical address of the frame.
|
||||
///
|
||||
/// The implemented structure should have a size less than or equal to
|
||||
/// [`FRAME_METADATA_MAX_SIZE`] and an alignment less than or equal to
|
||||
/// [`FRAME_METADATA_MAX_ALIGN`]. Otherwise, the metadata type cannot
|
||||
/// be used because storing it will fail compile-time assertions.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The implemented structure must have a size less than or equal to
|
||||
/// [`FRAME_METADATA_MAX_SIZE`] and an alignment less than or equal to
|
||||
/// [`FRAME_METADATA_MAX_ALIGN`].
|
||||
///
|
||||
/// The implementer of the `on_drop` method should ensure that the frame is
|
||||
/// safe to be read.
|
||||
/// If `on_drop` reads the page using the provided `VmReader`, the
|
||||
/// implementer must ensure that the frame is safe to read.
|
||||
pub unsafe trait AnyFrameMeta: Any + Send + Sync + Debug + 'static {
|
||||
/// Called when the last handle to the frame is dropped.
|
||||
fn on_drop(&mut self, reader: &mut VmReader<Infallible>) {
|
||||
let _ = reader;
|
||||
}
|
||||
fn on_drop(&mut self, _reader: &mut VmReader<Infallible>) {}
|
||||
|
||||
/// Whether the metadata's associated frame is untyped.
|
||||
///
|
||||
@ -160,18 +159,11 @@ pub unsafe trait AnyFrameMeta: Any + Send + Sync + Debug + 'static {
|
||||
}
|
||||
|
||||
/// Makes a structure usable as a frame metadata.
|
||||
///
|
||||
/// Directly implementing [`AnyFrameMeta`] is not safe since the size and alignment
|
||||
/// must be checked. This macro provides a safe way to implement the trait with
|
||||
/// compile-time checks.
|
||||
#[macro_export]
|
||||
macro_rules! impl_frame_meta_for {
|
||||
// Implement without specifying the drop behavior.
|
||||
($t:ty) => {
|
||||
use static_assertions::const_assert;
|
||||
const_assert!(size_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_SIZE);
|
||||
const_assert!(align_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_ALIGN);
|
||||
// SAFETY: The size and alignment of the structure are checked.
|
||||
// SAFETY: `on_drop` won't read the page.
|
||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {}
|
||||
};
|
||||
}
|
||||
@ -358,11 +350,8 @@ impl MetaSlot {
|
||||
///
|
||||
/// The caller should have exclusive access to the metadata slot's fields.
|
||||
pub(super) unsafe fn write_meta<M: AnyFrameMeta>(&self, metadata: M) {
|
||||
// Checking unsafe preconditions of the `AnyFrameMeta` trait.
|
||||
// We can't debug assert until we fix the constant generic bonds in
|
||||
// the linked list meta.
|
||||
assert!(size_of::<M>() <= FRAME_METADATA_MAX_SIZE);
|
||||
assert!(align_of::<M>() <= FRAME_METADATA_MAX_ALIGN);
|
||||
const { assert!(size_of::<M>() <= FRAME_METADATA_MAX_SIZE) };
|
||||
const { assert!(align_of::<M>() <= FRAME_METADATA_MAX_ALIGN) };
|
||||
|
||||
// SAFETY: Caller ensures that the access to the fields are exclusive.
|
||||
let vtable_ptr = unsafe { &mut *self.vtable_ptr.get() };
|
||||
@ -372,7 +361,7 @@ impl MetaSlot {
|
||||
// SAFETY:
|
||||
// 1. `ptr` points to the metadata storage.
|
||||
// 2. The size and the alignment of the metadata storage is large enough to hold `M`
|
||||
// (guaranteed by the safety requirement of the `AnyFrameMeta` trait).
|
||||
// (guaranteed by the const assertions above).
|
||||
// 3. We have exclusive access to the metadata storage (guaranteed by the caller).
|
||||
unsafe { ptr.cast::<M>().write(metadata) };
|
||||
}
|
||||
|
@ -34,19 +34,12 @@ pub type UFrame = Frame<dyn AnyUFrameMeta>;
|
||||
|
||||
/// Makes a structure usable as untyped frame metadata.
|
||||
///
|
||||
/// Directly implementing [`AnyFrameMeta`] is not safe since the size and
|
||||
/// alignment must be checked. This macro provides a safe way to implement both
|
||||
/// [`AnyFrameMeta`] and [`AnyUFrameMeta`] with compile-time checks.
|
||||
///
|
||||
/// If this macro is used for built-in typed frame metadata, it won't compile.
|
||||
#[macro_export]
|
||||
macro_rules! impl_untyped_frame_meta_for {
|
||||
// Implement without specifying the drop behavior.
|
||||
($t:ty) => {
|
||||
use static_assertions::const_assert;
|
||||
const_assert!(size_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_SIZE);
|
||||
const_assert!(align_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_ALIGN);
|
||||
// SAFETY: The size and alignment of the structure are checked.
|
||||
// SAFETY: Untyped frames can be safely read.
|
||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
||||
fn is_untyped(&self) -> bool {
|
||||
true
|
||||
@ -56,12 +49,7 @@ macro_rules! impl_untyped_frame_meta_for {
|
||||
};
|
||||
// Implement with a customized drop function.
|
||||
($t:ty, $body:expr) => {
|
||||
use static_assertions::const_assert;
|
||||
const_assert!(size_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_SIZE);
|
||||
const_assert!(align_of::<$t>() <= $crate::mm::frame::meta::FRAME_METADATA_MAX_ALIGN);
|
||||
// SAFETY: The size and alignment of the structure are checked.
|
||||
// Outside OSTD the user cannot implement a `on_drop` method for typed
|
||||
// frames. And untyped frames can be safely read.
|
||||
// SAFETY: Untyped frames can be safely read.
|
||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
||||
fn on_drop(&mut self, reader: &mut $crate::mm::VmReader<$crate::mm::Infallible>) {
|
||||
$body
|
||||
|
Loading…
x
Reference in New Issue
Block a user