mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Add ForceSync
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
85a7d94da7
commit
51db2da151
@ -7,12 +7,17 @@ mod kernel_stack;
|
|||||||
mod preempt;
|
mod preempt;
|
||||||
mod processor;
|
mod processor;
|
||||||
pub mod scheduler;
|
pub mod scheduler;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use core::{any::Any, cell::SyncUnsafeCell};
|
use core::{
|
||||||
|
any::Any,
|
||||||
|
cell::{Cell, SyncUnsafeCell},
|
||||||
|
};
|
||||||
|
|
||||||
use kernel_stack::KernelStack;
|
use kernel_stack::KernelStack;
|
||||||
pub(crate) use preempt::cpu_local::reset_preempt_info;
|
pub(crate) use preempt::cpu_local::reset_preempt_info;
|
||||||
use processor::current_task;
|
use processor::current_task;
|
||||||
|
use utils::ForceSync;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
preempt::{disable_preempt, DisabledPreemptGuard},
|
preempt::{disable_preempt, DisabledPreemptGuard},
|
||||||
@ -28,7 +33,8 @@ use crate::{prelude::*, user::UserSpace};
|
|||||||
/// execute user code. Multiple tasks can share a single user space.
|
/// execute user code. Multiple tasks can share a single user space.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
func: SyncUnsafeCell<Option<Box<dyn FnOnce() + Send + Sync>>>,
|
#[allow(clippy::type_complexity)]
|
||||||
|
func: ForceSync<Cell<Option<Box<dyn FnOnce() + Send>>>>,
|
||||||
data: Box<dyn Any + Send + Sync>,
|
data: Box<dyn Any + Send + Sync>,
|
||||||
user_space: Option<Arc<UserSpace>>,
|
user_space: Option<Arc<UserSpace>>,
|
||||||
ctx: SyncUnsafeCell<TaskContext>,
|
ctx: SyncUnsafeCell<TaskContext>,
|
||||||
@ -104,7 +110,7 @@ impl Task {
|
|||||||
|
|
||||||
/// Options to create or spawn a new task.
|
/// Options to create or spawn a new task.
|
||||||
pub struct TaskOptions {
|
pub struct TaskOptions {
|
||||||
func: Option<Box<dyn FnOnce() + Send + Sync>>,
|
func: Option<Box<dyn FnOnce() + Send>>,
|
||||||
data: Option<Box<dyn Any + Send + Sync>>,
|
data: Option<Box<dyn Any + Send + Sync>>,
|
||||||
user_space: Option<Arc<UserSpace>>,
|
user_space: Option<Arc<UserSpace>>,
|
||||||
}
|
}
|
||||||
@ -125,7 +131,7 @@ impl TaskOptions {
|
|||||||
/// Sets the function that represents the entry point of the task.
|
/// Sets the function that represents the entry point of the task.
|
||||||
pub fn func<F>(mut self, func: F) -> Self
|
pub fn func<F>(mut self, func: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn() + Send + Sync + 'static,
|
F: Fn() + Send + 'static,
|
||||||
{
|
{
|
||||||
self.func = Some(Box::new(func));
|
self.func = Some(Box::new(func));
|
||||||
self
|
self
|
||||||
@ -153,9 +159,10 @@ impl TaskOptions {
|
|||||||
extern "C" fn kernel_task_entry() -> ! {
|
extern "C" fn kernel_task_entry() -> ! {
|
||||||
let current_task = current_task()
|
let current_task = current_task()
|
||||||
.expect("no current task, it should have current task in kernel task entry");
|
.expect("no current task, it should have current task in kernel task entry");
|
||||||
// SAFETY: The scheduler will ensure that the task is only accessed
|
|
||||||
// by one CPU.
|
// SAFETY: The `func` field will only be accessed by the current task in the task
|
||||||
let task_func = unsafe { &mut *current_task.func.get() };
|
// context, so the data won't be accessed concurrently.
|
||||||
|
let task_func = unsafe { current_task.func.get() };
|
||||||
let task_func = task_func
|
let task_func = task_func
|
||||||
.take()
|
.take()
|
||||||
.expect("task function is `None` when trying to run");
|
.expect("task function is `None` when trying to run");
|
||||||
@ -186,7 +193,7 @@ impl TaskOptions {
|
|||||||
ctx.get_mut().set_stack_pointer(kstack.end_vaddr() - 16);
|
ctx.get_mut().set_stack_pointer(kstack.end_vaddr() - 16);
|
||||||
|
|
||||||
let new_task = Task {
|
let new_task = Task {
|
||||||
func: SyncUnsafeCell::new(self.func),
|
func: ForceSync::new(Cell::new(self.func)),
|
||||||
data: self.data.unwrap(),
|
data: self.data.unwrap(),
|
||||||
user_space: self.user_space,
|
user_space: self.user_space,
|
||||||
ctx,
|
ctx,
|
||||||
|
33
ostd/src/task/utils.rs
Normal file
33
ostd/src/task/utils.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use alloc::fmt;
|
||||||
|
|
||||||
|
/// Always [`Sync`], but unsafe to reference the data.
|
||||||
|
pub(super) struct ForceSync<T>(T);
|
||||||
|
|
||||||
|
impl<T> fmt::Debug for ForceSync<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("ForceSync").finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: The caller of the `ForceSync::get` method must ensure that the underlying data is not
|
||||||
|
// concurrently accessed if the underlying type is not `Sync`.
|
||||||
|
unsafe impl<T> Sync for ForceSync<T> {}
|
||||||
|
|
||||||
|
impl<T> ForceSync<T> {
|
||||||
|
/// Creates an instance with `data` as the inner data.
|
||||||
|
pub(super) fn new(data: T) -> Self {
|
||||||
|
Self(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the inner data.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// If the data type is not [`Sync`], the caller must ensure that the data is not accessed
|
||||||
|
/// concurrently.
|
||||||
|
pub(super) unsafe fn get(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user