2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2024-06-19 08:18:39 +00:00
|
|
|
use ostd::{
|
2024-02-25 14:09:24 +00:00
|
|
|
cpu::CpuSet,
|
2024-09-14 07:32:21 +00:00
|
|
|
task::{Task, TaskOptions},
|
2024-02-25 14:09:24 +00:00
|
|
|
};
|
2022-12-20 06:12:22 +00:00
|
|
|
|
2024-10-21 09:32:28 +00:00
|
|
|
use super::{oops, status::ThreadStatus, Thread};
|
2024-09-14 07:32:21 +00:00
|
|
|
use crate::{prelude::*, sched::priority::Priority};
|
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 {
|
|
|
|
|
func: Option<Box<dyn Fn() + Send + Sync>>,
|
2023-10-08 16:02:24 +00:00
|
|
|
priority: Priority,
|
|
|
|
|
cpu_affinity: CpuSet,
|
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
|
|
|
|
|
F: Fn() + Send + Sync + 'static,
|
|
|
|
|
{
|
2023-10-08 16:02:24 +00:00
|
|
|
let cpu_affinity = CpuSet::new_full();
|
2023-09-28 05:34:06 +00:00
|
|
|
Self {
|
|
|
|
|
func: Some(Box::new(func)),
|
2024-09-14 07:32:21 +00:00
|
|
|
priority: Priority::default(),
|
2023-10-08 16:02:24 +00:00
|
|
|
cpu_affinity,
|
2023-09-28 05:34:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-10 08:48:35 +00:00
|
|
|
/// Sets the priority of the new thread.
|
2023-10-08 16:02:24 +00:00
|
|
|
pub fn priority(mut self, priority: Priority) -> Self {
|
2023-09-28 05:34:06 +00:00
|
|
|
self.priority = priority;
|
|
|
|
|
self
|
|
|
|
|
}
|
2023-10-08 16:02:24 +00:00
|
|
|
|
2024-11-10 08:48:35 +00:00
|
|
|
/// Sets the CPU affinity of the new thread.
|
2023-10-08 16:02:24 +00:00
|
|
|
pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self {
|
|
|
|
|
self.cpu_affinity = cpu_affinity;
|
|
|
|
|
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 status = ThreadStatus::Init;
|
|
|
|
|
let priority = self.priority;
|
|
|
|
|
let cpu_affinity = self.cpu_affinity;
|
|
|
|
|
Arc::new(Thread::new(
|
|
|
|
|
weak_task.clone(),
|
|
|
|
|
kernel_thread,
|
|
|
|
|
status,
|
|
|
|
|
priority,
|
|
|
|
|
cpu_affinity,
|
|
|
|
|
))
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TaskOptions::new(thread_fn).data(thread).build().unwrap()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a new kernel thread and runs it immediately.
|
|
|
|
|
pub fn spawn(self) -> Arc<Thread> {
|
|
|
|
|
let task = self.build();
|
|
|
|
|
let thread = Thread::borrow_from_task(&task).clone();
|
|
|
|
|
thread.run();
|
|
|
|
|
thread
|
|
|
|
|
}
|
|
|
|
|
}
|