asterinas/kernel/src/thread/kernel_thread.rs

88 lines
2.3 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
2024-06-19 08:18:39 +00:00
use ostd::{
cpu::CpuSet,
task::{Task, TaskOptions},
};
2022-12-20 06:12:22 +00:00
2024-08-17 08:06:35 +00:00
use super::{oops, AsThread, Thread};
2025-01-22 06:08:35 +00:00
use crate::{
prelude::*,
sched::{Nice, SchedPolicy},
};
2022-12-20 06:12:22 +00:00
2024-11-10 08:48:35 +00:00
/// The inner data of a kernel thread.
struct KernelThread;
2022-12-20 06:12:22 +00:00
2024-11-10 08:48:35 +00:00
/// Options to create or spawn a new kernel thread.
2023-09-28 05:34:06 +00:00
pub struct ThreadOptions {
2025-01-18 23:45:04 +00:00
func: Option<Box<dyn FnOnce() + Send>>,
cpu_affinity: CpuSet,
2025-01-22 06:08:35 +00:00
sched_policy: SchedPolicy,
2023-09-28 05:34:06 +00:00
}
impl ThreadOptions {
2024-11-10 08:48:35 +00:00
/// Creates the thread options with the thread function.
2023-09-28 05:34:06 +00:00
pub fn new<F>(func: F) -> Self
where
2025-01-18 23:45:04 +00:00
F: FnOnce() + Send + 'static,
2023-09-28 05:34:06 +00:00
{
let cpu_affinity = CpuSet::new_full();
2025-01-22 06:08:35 +00:00
let sched_policy = SchedPolicy::Fair(Nice::default());
2023-09-28 05:34:06 +00:00
Self {
func: Some(Box::new(func)),
cpu_affinity,
2025-01-22 06:08:35 +00:00
sched_policy,
2023-09-28 05:34:06 +00:00
}
}
2024-11-10 08:48:35 +00:00
/// Sets the CPU affinity of the new thread.
pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self {
self.cpu_affinity = cpu_affinity;
self
}
2025-01-22 06:08:35 +00:00
/// Sets the scheduling policy.
pub fn sched_policy(mut self, sched_policy: SchedPolicy) -> Self {
self.sched_policy = sched_policy;
self
}
2023-09-28 05:34:06 +00:00
}
2024-11-10 08:48:35 +00:00
impl ThreadOptions {
/// Builds a new kernel thread without running it immediately.
pub fn build(mut self) -> Arc<Task> {
let task_fn = self.func.take().unwrap();
let thread_fn = move || {
let _ = oops::catch_panics_as_oops(task_fn);
// Ensure that the thread exits.
current_thread!().exit();
};
Arc::new_cyclic(|weak_task| {
let thread = {
let kernel_thread = KernelThread;
let cpu_affinity = self.cpu_affinity;
2025-01-22 06:08:35 +00:00
let sched_policy = self.sched_policy;
2024-11-10 08:48:35 +00:00
Arc::new(Thread::new(
weak_task.clone(),
kernel_thread,
cpu_affinity,
2025-01-22 06:08:35 +00:00
sched_policy,
2024-11-10 08:48:35 +00:00
))
};
TaskOptions::new(thread_fn).data(thread).build().unwrap()
})
}
/// Builds a new kernel thread and runs it immediately.
#[track_caller]
2024-11-10 08:48:35 +00:00
pub fn spawn(self) -> Arc<Thread> {
let task = self.build();
let thread = task.as_thread().unwrap().clone();
2024-11-10 08:48:35 +00:00
thread.run();
thread
}
}