Make task store Arc<Thread> and process store Arc<Task>

This commit is contained in:
Jianfeng Jiang
2024-09-13 03:13:07 +00:00
committed by Tate, Hongliang Tian
parent 81b0f265b5
commit f3174dbbbc
22 changed files with 255 additions and 246 deletions

View File

@ -2,23 +2,22 @@
use ostd::{
cpu::CpuSet,
task::{Priority, TaskOptions},
task::{Priority, Task, TaskOptions},
};
use super::{status::ThreadStatus, thread_table, Thread};
use super::{status::ThreadStatus, Thread};
use crate::prelude::*;
/// The inner data of a kernel thread
pub struct KernelThread;
pub trait KernelThreadExt {
/// get the kernel_thread structure
/// Gets the kernel_thread structure
fn as_kernel_thread(&self) -> Option<&KernelThread>;
/// create a new kernel thread structure, **NOT** run the thread.
fn new_kernel_thread(thread_options: ThreadOptions) -> Arc<Thread>;
/// create a new kernel thread structure, and then run the thread.
/// Creates a new kernel thread, and then run the thread.
fn spawn_kernel_thread(thread_options: ThreadOptions) -> Arc<Thread> {
let thread = Self::new_kernel_thread(thread_options);
let task = create_new_kernel_task(thread_options);
let thread = Thread::borrow_from_task(&task).clone();
thread.run();
thread
}
@ -31,31 +30,6 @@ impl KernelThreadExt for Thread {
self.data().downcast_ref::<KernelThread>()
}
fn new_kernel_thread(mut thread_options: ThreadOptions) -> Arc<Self> {
let task_fn = thread_options.take_func();
let thread_fn = move || {
task_fn();
let current_thread = current_thread!();
// ensure the thread is exit
current_thread.exit();
thread_table::remove_kernel_thread(current_thread);
};
let thread = Arc::new_cyclic(|thread_ref| {
let weak_thread = thread_ref.clone();
let task = TaskOptions::new(thread_fn)
.data(weak_thread)
.priority(thread_options.priority)
.cpu_affinity(thread_options.cpu_affinity)
.build()
.unwrap();
let status = ThreadStatus::Init;
let kernel_thread = KernelThread;
Thread::new(task, kernel_thread, status)
});
thread_table::add_kernel_thread(thread.clone());
thread
}
fn join(&self) {
loop {
if self.status().is_exited() {
@ -67,6 +41,31 @@ impl KernelThreadExt for Thread {
}
}
/// Creates a new task of kernel thread, **NOT** run the thread.
pub fn create_new_kernel_task(mut thread_options: ThreadOptions) -> Arc<Task> {
let task_fn = thread_options.take_func();
let thread_fn = move || {
task_fn();
// Ensures the thread is exit
current_thread!().exit();
};
Arc::new_cyclic(|weak_task| {
let thread = {
let kernel_thread = KernelThread;
let status = ThreadStatus::Init;
Arc::new(Thread::new(weak_task.clone(), kernel_thread, status))
};
TaskOptions::new(thread_fn)
.data(thread)
.priority(thread_options.priority)
.cpu_affinity(thread_options.cpu_affinity)
.build()
.unwrap()
})
}
/// Options to create or spawn a new thread.
pub struct ThreadOptions {
func: Option<Box<dyn Fn() + Send + Sync>>,

View File

@ -13,7 +13,6 @@ pub mod exception;
pub mod kernel_thread;
pub mod status;
pub mod task;
pub mod thread_table;
pub mod work_queue;
pub type Tid = u32;
@ -22,7 +21,7 @@ pub type Tid = u32;
pub struct Thread {
// immutable part
/// Low-level info
task: Arc<Task>,
task: Weak<Task>,
/// Data: Posix thread info/Kernel thread Info
data: Box<dyn Send + Sync + Any>,
@ -32,7 +31,7 @@ pub struct Thread {
impl Thread {
/// Never call these function directly
pub fn new(task: Arc<Task>, data: impl Send + Sync + Any, status: ThreadStatus) -> Self {
pub fn new(task: Weak<Task>, data: impl Send + Sync + Any, status: ThreadStatus) -> Self {
Thread {
task,
data: Box::new(data),
@ -47,18 +46,23 @@ impl Thread {
pub fn current() -> Option<Arc<Self>> {
Task::current()?
.data()
.downcast_ref::<Weak<Thread>>()?
.upgrade()
.downcast_ref::<Arc<Thread>>()
.cloned()
}
pub(in crate::thread) fn task(&self) -> &Arc<Task> {
&self.task
/// Gets the Thread from task's data.
///
/// # Panics
///
/// This method panics if the task is not a thread.
pub fn borrow_from_task(task: &Arc<Task>) -> &Arc<Self> {
task.data().downcast_ref::<Arc<Thread>>().unwrap()
}
/// Runs this thread at once.
pub fn run(&self) {
self.set_status(ThreadStatus::Running);
self.task.run();
self.task.upgrade().unwrap().run();
}
pub(super) fn exit(&self) {

View File

@ -16,12 +16,12 @@ use crate::{
};
/// create new task with userspace and parent process
pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>) -> Arc<Task> {
pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Arc<Thread>) -> Task {
fn user_task_entry() {
let current_thread = current_thread!();
let current_posix_thread = current_thread.as_posix_thread().unwrap();
let current_process = current_posix_thread.process();
let current_task = current_thread.task();
let current_task = Task::current().unwrap();
let user_space = current_task
.user_space()

View File

@ -1,30 +0,0 @@
// SPDX-License-Identifier: MPL-2.0
use keyable_arc::KeyableArc;
use super::{Thread, Tid};
use crate::{prelude::*, process::posix_thread::PosixThreadExt};
static POSIX_THREAD_TABLE: SpinLock<BTreeMap<Tid, Arc<Thread>>> = SpinLock::new(BTreeMap::new());
static KERNEL_THREAD_TABLE: SpinLock<BTreeSet<KeyableArc<Thread>>> = SpinLock::new(BTreeSet::new());
pub fn add_posix_thread(tid: Tid, thread: Arc<Thread>) {
debug_assert_eq!(tid, thread.tid());
POSIX_THREAD_TABLE.lock().insert(tid, thread);
}
pub fn remove_posix_thread(tid: Tid) {
POSIX_THREAD_TABLE.lock().remove(&tid);
}
pub fn get_posix_thread(tid: Tid) -> Option<Arc<Thread>> {
POSIX_THREAD_TABLE.lock().get(&tid).cloned()
}
pub(super) fn add_kernel_thread(thread: Arc<Thread>) {
KERNEL_THREAD_TABLE.lock().insert(KeyableArc::from(thread));
}
pub(super) fn remove_kernel_thread(thread: Arc<Thread>) {
KERNEL_THREAD_TABLE.lock().remove(&KeyableArc::from(thread));
}

View File

@ -2,12 +2,15 @@
#![allow(dead_code)]
use ostd::{cpu::CpuSet, task::Priority};
use ostd::{
cpu::CpuSet,
task::{Priority, Task},
};
use super::worker_pool::WorkerPool;
use crate::{
prelude::*,
thread::kernel_thread::{KernelThreadExt, ThreadOptions},
thread::kernel_thread::{create_new_kernel_task, ThreadOptions},
Thread,
};
@ -17,7 +20,7 @@ use crate::{
/// added to the `WorkerPool`.
pub(super) struct Worker {
worker_pool: Weak<WorkerPool>,
bound_thread: Arc<Thread>,
bound_task: Arc<Task>,
bound_cpu: u32,
inner: SpinLock<WorkerInner>,
}
@ -51,14 +54,14 @@ impl Worker {
if worker_pool.upgrade().unwrap().is_high_priority() {
priority = Priority::high();
}
let bound_thread = Thread::new_kernel_thread(
let bound_task = create_new_kernel_task(
ThreadOptions::new(task_fn)
.cpu_affinity(cpu_affinity)
.priority(priority),
);
Self {
worker_pool,
bound_thread,
bound_task,
bound_cpu,
inner: SpinLock::new(WorkerInner {
worker_status: WorkerStatus::Running,
@ -68,7 +71,8 @@ impl Worker {
}
pub(super) fn run(&self) {
self.bound_thread.run();
let thread = Thread::borrow_from_task(&self.bound_task);
thread.run();
}
/// The thread function bound to normal workers.
@ -97,8 +101,8 @@ impl Worker {
self.exit();
}
pub(super) fn bound_thread(&self) -> &Arc<Thread> {
&self.bound_thread
pub(super) fn bound_task(&self) -> &Arc<Task> {
&self.bound_task
}
pub(super) fn is_idle(&self) -> bool {

View File

@ -7,12 +7,16 @@ use core::{
time::Duration,
};
use ostd::{cpu::CpuSet, sync::WaitQueue, task::Priority};
use ostd::{
cpu::CpuSet,
sync::WaitQueue,
task::{Priority, Task},
};
use super::{simple_scheduler::SimpleScheduler, worker::Worker, WorkItem, WorkPriority, WorkQueue};
use crate::{
prelude::*,
thread::kernel_thread::{KernelThreadExt, ThreadOptions},
thread::kernel_thread::{create_new_kernel_task, ThreadOptions},
Thread,
};
@ -60,7 +64,7 @@ pub trait WorkerScheduler: Sync + Send {
/// are found processing in the pool.
pub struct Monitor {
worker_pool: Weak<WorkerPool>,
bound_thread: Arc<Thread>,
bound_task: Arc<Task>,
}
impl LocalWorkerPool {
@ -77,7 +81,7 @@ impl LocalWorkerPool {
fn add_worker(&self) {
let worker = Worker::new(self.parent.clone(), self.cpu_id);
self.workers.disable_irq().lock().push_back(worker.clone());
worker.bound_thread().run();
Thread::borrow_from_task(worker.bound_task()).run();
}
fn remove_worker(&self) {
@ -236,20 +240,20 @@ impl Monitor {
WorkPriority::High => Priority::high(),
WorkPriority::Normal => Priority::normal(),
};
let bound_thread = Thread::new_kernel_thread(
let bound_task = create_new_kernel_task(
ThreadOptions::new(task_fn)
.cpu_affinity(cpu_affinity)
.priority(priority),
);
Self {
worker_pool,
bound_thread,
bound_task,
}
})
}
pub fn run(&self) {
self.bound_thread.run();
Thread::borrow_from_task(&self.bound_task).run()
}
fn run_monitor_loop(self: &Arc<Self>) {