asterinas/kernel/aster-nix/src/thread/kernel_thread.rs

112 lines
3.1 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
use aster_frame::{
cpu::CpuSet,
task::{Priority, TaskOptions},
};
2022-12-20 06:12:22 +00:00
use super::{allocate_tid, status::ThreadStatus, thread_table, Thread};
use crate::prelude::*;
2022-12-20 06:12:22 +00:00
2023-03-07 08:10:15 +00:00
/// The inner data of a kernel thread
2023-03-07 06:24:29 +00:00
pub struct KernelThread;
2022-12-20 06:12:22 +00:00
pub trait KernelThreadExt {
2023-03-07 06:24:29 +00:00
/// get the kernel_thread structure
2023-03-07 08:10:15 +00:00
fn as_kernel_thread(&self) -> Option<&KernelThread>;
2023-03-07 06:24:29 +00:00
/// create a new kernel thread structure, **NOT** run the thread.
2023-09-28 05:34:06 +00:00
fn new_kernel_thread(thread_options: ThreadOptions) -> Arc<Thread>;
2023-03-07 06:24:29 +00:00
/// create a new kernel thread structure, and then run the thread.
2023-09-28 05:34:06 +00:00
fn spawn_kernel_thread(thread_options: ThreadOptions) -> Arc<Thread> {
let thread = Self::new_kernel_thread(thread_options);
2023-03-07 06:24:29 +00:00
thread.run();
thread
}
2023-03-13 07:59:01 +00:00
/// join a kernel thread, returns if the kernel thread exit
2023-03-07 06:24:29 +00:00
fn join(&self);
2022-12-20 06:12:22 +00:00
}
impl KernelThreadExt for Thread {
2023-03-07 08:10:15 +00:00
fn as_kernel_thread(&self) -> Option<&KernelThread> {
self.data().downcast_ref::<KernelThread>()
2022-12-20 06:12:22 +00:00
}
2023-09-28 05:34:06 +00:00
fn new_kernel_thread(mut thread_options: ThreadOptions) -> Arc<Self> {
let task_fn = thread_options.take_func();
2023-03-07 06:24:29 +00:00
let thread_fn = move || {
task_fn();
let current_thread = current_thread!();
// ensure the thread is exit
current_thread.exit();
};
2022-12-20 06:12:22 +00:00
let tid = allocate_tid();
let thread = Arc::new_cyclic(|thread_ref| {
2023-09-28 05:34:06 +00:00
let weal_thread = thread_ref.clone();
let task = TaskOptions::new(thread_fn)
.data(weal_thread)
.priority(thread_options.priority)
.cpu_affinity(thread_options.cpu_affinity)
2023-09-28 05:34:06 +00:00
.build()
.unwrap();
2022-12-20 06:12:22 +00:00
let status = ThreadStatus::Init;
2023-03-07 06:24:29 +00:00
let kernel_thread = KernelThread;
2022-12-20 06:12:22 +00:00
Thread::new(tid, task, kernel_thread, status)
});
thread_table::add_thread(thread.clone());
thread
}
2023-03-07 06:24:29 +00:00
fn join(&self) {
loop {
if self.status().is_exited() {
2023-03-07 06:24:29 +00:00
return;
} else {
Thread::yield_now();
}
}
}
2022-12-20 06:12:22 +00:00
}
2023-09-28 05:34:06 +00:00
/// Options to create or spawn a new thread.
pub struct ThreadOptions {
func: Option<Box<dyn Fn() + Send + Sync>>,
priority: Priority,
cpu_affinity: CpuSet,
2023-09-28 05:34:06 +00:00
}
impl ThreadOptions {
pub fn new<F>(func: F) -> Self
where
F: Fn() + Send + Sync + 'static,
{
let cpu_affinity = CpuSet::new_full();
2023-09-28 05:34:06 +00:00
Self {
func: Some(Box::new(func)),
priority: Priority::normal(),
cpu_affinity,
2023-09-28 05:34:06 +00:00
}
}
pub fn func<F>(mut self, func: F) -> Self
where
F: Fn() + Send + Sync + 'static,
{
self.func = Some(Box::new(func));
self
}
fn take_func(&mut self) -> Box<dyn Fn() + Send + Sync> {
self.func.take().unwrap()
}
pub fn priority(mut self, priority: Priority) -> Self {
2023-09-28 05:34:06 +00:00
self.priority = priority;
self
}
pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self {
self.cpu_affinity = cpu_affinity;
self
}
2023-09-28 05:34:06 +00:00
}