mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-16 17:46: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.
|
// SAFETY: If `M::on_drop` reads the page using the provided `VmReader`,
|
||||||
// Also, if `M` is typed, `Link<M>` must not be untyped.
|
// the safety is upheld by the one who implements `AnyFrameMeta` for `M`.
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
unsafe impl<M> AnyFrameMeta for Link<M>
|
unsafe impl<M> AnyFrameMeta for Link<M>
|
||||||
where
|
where
|
||||||
M: AnyFrameMeta,
|
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`
|
/// this frame, the `on_drop` method will be called. The `on_drop`
|
||||||
/// method is called with the physical address of the frame.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The implemented structure must have a size less than or equal to
|
/// If `on_drop` reads the page using the provided `VmReader`, the
|
||||||
/// [`FRAME_METADATA_MAX_SIZE`] and an alignment less than or equal to
|
/// implementer must ensure that the frame is safe to read.
|
||||||
/// [`FRAME_METADATA_MAX_ALIGN`].
|
|
||||||
///
|
|
||||||
/// The implementer of the `on_drop` method should ensure that the frame is
|
|
||||||
/// safe to be read.
|
|
||||||
pub unsafe trait AnyFrameMeta: Any + Send + Sync + Debug + 'static {
|
pub unsafe trait AnyFrameMeta: Any + Send + Sync + Debug + 'static {
|
||||||
/// Called when the last handle to the frame is dropped.
|
/// Called when the last handle to the frame is dropped.
|
||||||
fn on_drop(&mut self, reader: &mut VmReader<Infallible>) {
|
fn on_drop(&mut self, _reader: &mut VmReader<Infallible>) {}
|
||||||
let _ = reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the metadata's associated frame is untyped.
|
/// 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.
|
/// 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_export]
|
||||||
macro_rules! impl_frame_meta_for {
|
macro_rules! impl_frame_meta_for {
|
||||||
// Implement without specifying the drop behavior.
|
// Implement without specifying the drop behavior.
|
||||||
($t:ty) => {
|
($t:ty) => {
|
||||||
use static_assertions::const_assert;
|
// SAFETY: `on_drop` won't read the page.
|
||||||
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.
|
|
||||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {}
|
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.
|
/// The caller should have exclusive access to the metadata slot's fields.
|
||||||
pub(super) unsafe fn write_meta<M: AnyFrameMeta>(&self, metadata: M) {
|
pub(super) unsafe fn write_meta<M: AnyFrameMeta>(&self, metadata: M) {
|
||||||
// Checking unsafe preconditions of the `AnyFrameMeta` trait.
|
const { assert!(size_of::<M>() <= FRAME_METADATA_MAX_SIZE) };
|
||||||
// We can't debug assert until we fix the constant generic bonds in
|
const { assert!(align_of::<M>() <= FRAME_METADATA_MAX_ALIGN) };
|
||||||
// the linked list meta.
|
|
||||||
assert!(size_of::<M>() <= FRAME_METADATA_MAX_SIZE);
|
|
||||||
assert!(align_of::<M>() <= FRAME_METADATA_MAX_ALIGN);
|
|
||||||
|
|
||||||
// SAFETY: Caller ensures that the access to the fields are exclusive.
|
// SAFETY: Caller ensures that the access to the fields are exclusive.
|
||||||
let vtable_ptr = unsafe { &mut *self.vtable_ptr.get() };
|
let vtable_ptr = unsafe { &mut *self.vtable_ptr.get() };
|
||||||
@ -372,7 +361,7 @@ impl MetaSlot {
|
|||||||
// SAFETY:
|
// SAFETY:
|
||||||
// 1. `ptr` points to the metadata storage.
|
// 1. `ptr` points to the metadata storage.
|
||||||
// 2. The size and the alignment of the metadata storage is large enough to hold `M`
|
// 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).
|
// 3. We have exclusive access to the metadata storage (guaranteed by the caller).
|
||||||
unsafe { ptr.cast::<M>().write(metadata) };
|
unsafe { ptr.cast::<M>().write(metadata) };
|
||||||
}
|
}
|
||||||
|
@ -34,19 +34,12 @@ pub type UFrame = Frame<dyn AnyUFrameMeta>;
|
|||||||
|
|
||||||
/// Makes a structure usable as untyped frame metadata.
|
/// 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.
|
/// If this macro is used for built-in typed frame metadata, it won't compile.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_untyped_frame_meta_for {
|
macro_rules! impl_untyped_frame_meta_for {
|
||||||
// Implement without specifying the drop behavior.
|
// Implement without specifying the drop behavior.
|
||||||
($t:ty) => {
|
($t:ty) => {
|
||||||
use static_assertions::const_assert;
|
// SAFETY: Untyped frames can be safely read.
|
||||||
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.
|
|
||||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
||||||
fn is_untyped(&self) -> bool {
|
fn is_untyped(&self) -> bool {
|
||||||
true
|
true
|
||||||
@ -56,12 +49,7 @@ macro_rules! impl_untyped_frame_meta_for {
|
|||||||
};
|
};
|
||||||
// Implement with a customized drop function.
|
// Implement with a customized drop function.
|
||||||
($t:ty, $body:expr) => {
|
($t:ty, $body:expr) => {
|
||||||
use static_assertions::const_assert;
|
// SAFETY: Untyped frames can be safely read.
|
||||||
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.
|
|
||||||
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
|
||||||
fn on_drop(&mut self, reader: &mut $crate::mm::VmReader<$crate::mm::Infallible>) {
|
fn on_drop(&mut self, reader: &mut $crate::mm::VmReader<$crate::mm::Infallible>) {
|
||||||
$body
|
$body
|
||||||
|
Loading…
x
Reference in New Issue
Block a user