CpuLocalCell::as_ptr_mut should be safe

This commit is contained in:
Ruihan Li
2024-11-20 09:43:15 +08:00
committed by Tate, Hongliang Tian
parent 3d63ed7a4c
commit b6944e48bd
2 changed files with 15 additions and 10 deletions

View File

@ -79,7 +79,7 @@ macro_rules! cpu_local_cell {
pub struct CpuLocalCell<T: 'static>(UnsafeCell<T>); pub struct CpuLocalCell<T: 'static>(UnsafeCell<T>);
impl<T: 'static> CpuLocalCell<T> { impl<T: 'static> CpuLocalCell<T> {
/// Initialize a CPU-local object. /// Initializes a CPU-local object.
/// ///
/// Please do not call this function directly. Instead, use the /// Please do not call this function directly. Instead, use the
/// `cpu_local!` macro. /// `cpu_local!` macro.
@ -94,17 +94,22 @@ impl<T: 'static> CpuLocalCell<T> {
Self(UnsafeCell::new(val)) Self(UnsafeCell::new(val))
} }
/// Get access to the underlying value through a raw pointer. /// Gets access to the underlying value through a raw pointer.
/// ///
/// This function calculates the virtual address of the CPU-local object /// This function calculates the virtual address of the CPU-local object
/// based on the CPU-local base address and the offset in the BSP. /// based on the CPU-local base address and the offset in the BSP.
/// ///
/// # Safety /// This method is safe, but using the returned pointer will be unsafe.
/// /// Specifically,
/// The caller should ensure that within the entire execution of this /// - Preemption should be disabled from the time this method is called
/// function, no interrupt or preemption can occur. Otherwise, the /// to the time the pointer is used. Otherwise, the pointer may point
/// returned pointer may points to the variable in another CPU. /// to the variable on another CPU, making it difficult or impossible
pub unsafe fn as_ptr_mut(&'static self) -> *mut T { /// to determine if the data can be borrowed.
/// - If the variable can be used in interrupt handlers, borrowing the
/// data should be done with interrupts disabled. Otherwise, more care
/// must be taken to ensure that the borrowing rules are correctly
/// enforced, since the interrupts may come asynchronously.
pub fn as_ptr_mut(&'static self) -> *mut T {
super::has_init::assert_true(); super::has_init::assert_true();
let offset = { let offset = {

View File

@ -45,8 +45,8 @@ pub(super) fn switch_to_task(next_task: Arc<Task>) {
// Throughout this method, the task's context is alive and can be exclusively used. // Throughout this method, the task's context is alive and can be exclusively used.
current_task.ctx.get() current_task.ctx.get()
} else { } else {
// SAFETY: Interrupts are disabled, so the pointer is safe to be fetched. // Throughout this method, interrupts are disabled and the context can be exclusively used.
unsafe { BOOTSTRAP_CONTEXT.as_ptr_mut() } BOOTSTRAP_CONTEXT.as_ptr_mut()
}; };
let next_task_ctx_ptr = next_task.ctx().get().cast_const(); let next_task_ctx_ptr = next_task.ctx().get().cast_const();