Remove KernelThreadExt

This commit is contained in:
Ruihan Li
2024-11-10 16:48:35 +08:00
committed by Tate, Hongliang Tian
parent 7850f7e60a
commit a4a8807a20
11 changed files with 111 additions and 138 deletions

View File

@ -26,7 +26,6 @@ use crate::{
fs_resolver::FsPath, fs_resolver::FsPath,
}, },
prelude::*, prelude::*,
thread::kernel_thread::KernelThreadExt,
}; };
fn start_block_device(device_name: &str) -> Result<Arc<dyn BlockDevice>> { fn start_block_device(device_name: &str) -> Result<Arc<dyn BlockDevice>> {
@ -39,7 +38,7 @@ fn start_block_device(device_name: &str) -> Result<Arc<dyn BlockDevice>> {
virtio_block_device.handle_requests(); virtio_block_device.handle_requests();
} }
}; };
crate::Thread::spawn_kernel_thread(crate::ThreadOptions::new(task_fn)); crate::ThreadOptions::new(task_fn).spawn();
Ok(device) Ok(device)
} else { } else {
return_errno_with_message!(Errno::ENOENT, "Device does not exist") return_errno_with_message!(Errno::ENOENT, "Device does not exist")

View File

@ -200,10 +200,7 @@ mod test {
use super::*; use super::*;
use crate::{ use crate::{
fs::utils::Channel, fs::utils::Channel,
thread::{ thread::{kernel_thread::ThreadOptions, Thread},
kernel_thread::{KernelThreadExt, ThreadOptions},
Thread,
},
}; };
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -232,7 +229,7 @@ mod test {
let signal_writer = Arc::new(AtomicBool::new(false)); let signal_writer = Arc::new(AtomicBool::new(false));
let signal_reader = signal_writer.clone(); let signal_reader = signal_writer.clone();
let writer = Thread::spawn_kernel_thread(ThreadOptions::new(move || { let writer = ThreadOptions::new(move || {
let writer = writer_with_lock.lock().take().unwrap(); let writer = writer_with_lock.lock().take().unwrap();
if ordering == Ordering::ReadThenWrite { if ordering == Ordering::ReadThenWrite {
@ -244,9 +241,10 @@ mod test {
} }
write(writer); write(writer);
})); })
.spawn();
let reader = Thread::spawn_kernel_thread(ThreadOptions::new(move || { let reader = ThreadOptions::new(move || {
let reader = reader_with_lock.lock().take().unwrap(); let reader = reader_with_lock.lock().take().unwrap();
if ordering == Ordering::WriteThenRead { if ordering == Ordering::WriteThenRead {
@ -258,7 +256,8 @@ mod test {
} }
read(reader); read(reader);
})); })
.spawn();
writer.join(); writer.join();
reader.join(); reader.join();

View File

@ -43,10 +43,7 @@ use sched::priority::PriorityRange;
use crate::{ use crate::{
prelude::*, prelude::*,
sched::priority::Priority, sched::priority::Priority,
thread::{ thread::{kernel_thread::ThreadOptions, Thread},
kernel_thread::{KernelThreadExt, ThreadOptions},
Thread,
},
}; };
extern crate alloc; extern crate alloc;
@ -89,10 +86,9 @@ pub fn main() {
ostd::boot::smp::register_ap_entry(ap_init); ostd::boot::smp::register_ap_entry(ap_init);
// Spawn the first kernel thread on BSP. // Spawn the first kernel thread on BSP.
Thread::spawn_kernel_thread(
ThreadOptions::new(init_thread) ThreadOptions::new(init_thread)
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), .priority(Priority::new(PriorityRange::new(PriorityRange::MAX)))
); .spawn();
} }
pub fn init() { pub fn init() {
@ -122,11 +118,10 @@ fn ap_init() {
let cpu_id = preempt_guard.current_cpu(); let cpu_id = preempt_guard.current_cpu();
drop(preempt_guard); drop(preempt_guard);
Thread::spawn_kernel_thread(
ThreadOptions::new(ap_idle_thread) ThreadOptions::new(ap_idle_thread)
.cpu_affinity(cpu_id.into()) .cpu_affinity(cpu_id.into())
.priority(Priority::new(PriorityRange::new(PriorityRange::MAX))), .priority(Priority::new(PriorityRange::new(PriorityRange::MAX)))
); .spawn();
} }
fn init_thread() { fn init_thread() {
@ -139,9 +134,10 @@ fn init_thread() {
fs::lazy_init(); fs::lazy_init();
ipc::init(); ipc::init();
// driver::pci::virtio::block::block_device_test(); // driver::pci::virtio::block::block_device_test();
let thread = Thread::spawn_kernel_thread(ThreadOptions::new(|| { let thread = ThreadOptions::new(|| {
println!("[kernel] Hello world from kernel!"); println!("[kernel] Hello world from kernel!");
})); })
.spawn();
thread.join(); thread.join();
print_banner(); print_banner();

View File

@ -9,10 +9,7 @@ use ostd::timer::Jiffies;
use super::{ext::IfaceEx, Iface, IFACES}; use super::{ext::IfaceEx, Iface, IFACES};
use crate::{ use crate::{
sched::priority::{Priority, PriorityRange}, sched::priority::{Priority, PriorityRange},
thread::{ thread::kernel_thread::ThreadOptions,
kernel_thread::{KernelThreadExt, ThreadOptions},
Thread,
},
WaitTimeout, WaitTimeout,
}; };
@ -70,6 +67,7 @@ fn spawn_background_poll_thread(iface: Arc<Iface>) {
}; };
// FIXME: remove the use of real-time priority. // FIXME: remove the use of real-time priority.
let options = ThreadOptions::new(task_fn).priority(Priority::new(PriorityRange::new(0))); ThreadOptions::new(task_fn)
Thread::spawn_kernel_thread(options); .priority(Priority::new(PriorityRange::new(0)))
.spawn();
} }

View File

@ -217,10 +217,7 @@ mod test {
use ostd::prelude::*; use ostd::prelude::*;
use super::*; use super::*;
use crate::thread::{ use crate::thread::{kernel_thread::ThreadOptions, Thread};
kernel_thread::{KernelThreadExt, ThreadOptions},
Thread,
};
#[ktest] #[ktest]
fn test_waiter_pause() { fn test_waiter_pause() {
@ -230,12 +227,13 @@ mod test {
let boolean = Arc::new(AtomicBool::new(false)); let boolean = Arc::new(AtomicBool::new(false));
let boolean_cloned = boolean.clone(); let boolean_cloned = boolean.clone();
let thread = Thread::spawn_kernel_thread(ThreadOptions::new(move || { let thread = ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
boolean_cloned.store(true, Ordering::Relaxed); boolean_cloned.store(true, Ordering::Relaxed);
wait_queue_cloned.wake_all(); wait_queue_cloned.wake_all();
})); })
.spawn();
wait_queue wait_queue
.pause_until(|| boolean.load(Ordering::Relaxed).then_some(())) .pause_until(|| boolean.load(Ordering::Relaxed).then_some(()))

View File

@ -52,20 +52,21 @@ impl<Guard> LockErr<Guard> {
/// ```rust /// ```rust
/// use alloc::sync::Arc; /// use alloc::sync::Arc;
/// use ostd::sync::Mutex; /// use ostd::sync::Mutex;
/// use crate::{process::sync::Condvar, thread::{kernel_thread::KernelThreadExt, Thread}}; /// use crate::{process::sync::Condvar, thread::kernel_thread::Thread};
/// ///
/// // Initializing a shared condition between threads /// // Initializing a shared condition between threads
/// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = Arc::clone(&pair); /// let pair2 = Arc::clone(&pair);
/// ///
/// // Spawning a new kernel thread to change a shared state and notify the Condvar /// // Spawning a new kernel thread to change a shared state and notify the Condvar
/// Thread::spawn_kernel_thread(ThreadOptions::new(move || { /// ThreadOptions::new(move || {
/// let (lock, cvar) = &*pair2; /// let (lock, cvar) = &*pair2;
/// Thread::yield_now(); /// Thread::yield_now();
/// let mut started = lock.lock(); /// let mut started = lock.lock();
/// *started = true; // Modifying the shared state /// *started = true; // Modifying the shared state
/// cvar.notify_one(); // Notifying one waiting thread /// cvar.notify_one(); // Notifying one waiting thread
/// })); /// })
/// .spawn();
/// ///
/// // Main thread waiting for the shared state to be set to true /// // Main thread waiting for the shared state to be set to true
/// { /// {
@ -267,23 +268,21 @@ mod test {
use ostd::{prelude::*, sync::Mutex}; use ostd::{prelude::*, sync::Mutex};
use super::*; use super::*;
use crate::thread::{ use crate::thread::{kernel_thread::ThreadOptions, Thread};
kernel_thread::{KernelThreadExt, ThreadOptions},
Thread,
};
#[ktest] #[ktest]
fn test_condvar_wait() { fn test_condvar_wait() {
let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair); let pair2 = Arc::clone(&pair);
Thread::spawn_kernel_thread(ThreadOptions::new(move || { ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let mut started = lock.lock(); let mut started = lock.lock();
*started = true; *started = true;
cvar.notify_one(); cvar.notify_one();
})); })
.spawn();
{ {
let (lock, cvar) = &*pair; let (lock, cvar) = &*pair;
@ -300,13 +299,14 @@ mod test {
let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair); let pair2 = Arc::clone(&pair);
Thread::spawn_kernel_thread(ThreadOptions::new(move || { ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let mut started = lock.lock(); let mut started = lock.lock();
*started = true; *started = true;
cvar.notify_one(); cvar.notify_one();
})); })
.spawn();
{ {
let (lock, cvar) = &*pair; let (lock, cvar) = &*pair;
@ -325,13 +325,14 @@ mod test {
let pair = Arc::new((Mutex::new(true), Condvar::new())); let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair2 = Arc::clone(&pair); let pair2 = Arc::clone(&pair);
Thread::spawn_kernel_thread(ThreadOptions::new(move || { ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let mut started = lock.lock(); let mut started = lock.lock();
*started = false; *started = false;
cvar.notify_one(); cvar.notify_one();
})); })
.spawn();
{ {
let (lock, cvar) = &*pair; let (lock, cvar) = &*pair;
@ -347,13 +348,14 @@ mod test {
let pair = Arc::new((Mutex::new(true), Condvar::new())); let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair2 = Arc::clone(&pair); let pair2 = Arc::clone(&pair);
Thread::spawn_kernel_thread(ThreadOptions::new(move || { ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let mut started = lock.lock(); let mut started = lock.lock();
*started = false; *started = false;
cvar.notify_one(); cvar.notify_one();
})); })
.spawn();
{ {
let (lock, cvar) = &*pair; let (lock, cvar) = &*pair;

View File

@ -8,42 +8,47 @@ use ostd::{
use super::{oops, status::ThreadStatus, Thread}; use super::{oops, status::ThreadStatus, Thread};
use crate::{prelude::*, sched::priority::Priority}; use crate::{prelude::*, sched::priority::Priority};
/// The inner data of a kernel thread /// The inner data of a kernel thread.
pub struct KernelThread; struct KernelThread;
pub trait KernelThreadExt { /// Options to create or spawn a new kernel thread.
/// Gets the kernel_thread structure pub struct ThreadOptions {
fn as_kernel_thread(&self) -> Option<&KernelThread>; func: Option<Box<dyn Fn() + Send + Sync>>,
/// Creates a new kernel thread, and then run the thread. priority: Priority,
fn spawn_kernel_thread(thread_options: ThreadOptions) -> Arc<Thread> { cpu_affinity: CpuSet,
let task = create_new_kernel_task(thread_options);
let thread = Thread::borrow_from_task(&task).clone();
thread.run();
thread
}
/// join a kernel thread, returns if the kernel thread exit
fn join(&self);
} }
impl KernelThreadExt for Thread { impl ThreadOptions {
fn as_kernel_thread(&self) -> Option<&KernelThread> { /// Creates the thread options with the thread function.
self.data().downcast_ref::<KernelThread>() pub fn new<F>(func: F) -> Self
} where
F: Fn() + Send + Sync + 'static,
fn join(&self) { {
loop { let cpu_affinity = CpuSet::new_full();
if self.is_exited() { Self {
return; func: Some(Box::new(func)),
} else { priority: Priority::default(),
Thread::yield_now(); cpu_affinity,
}
}
} }
} }
/// Creates a new task of kernel thread, **NOT** run the thread. /// Sets the priority of the new thread.
pub fn create_new_kernel_task(mut thread_options: ThreadOptions) -> Arc<Task> { pub fn priority(mut self, priority: Priority) -> Self {
let task_fn = thread_options.take_func(); self.priority = priority;
self
}
/// Sets the CPU affinity of the new thread.
pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self {
self.cpu_affinity = cpu_affinity;
self
}
}
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 thread_fn = move || {
let _ = oops::catch_panics_as_oops(task_fn); let _ = oops::catch_panics_as_oops(task_fn);
// Ensure that the thread exits. // Ensure that the thread exits.
@ -54,8 +59,8 @@ pub fn create_new_kernel_task(mut thread_options: ThreadOptions) -> Arc<Task> {
let thread = { let thread = {
let kernel_thread = KernelThread; let kernel_thread = KernelThread;
let status = ThreadStatus::Init; let status = ThreadStatus::Init;
let priority = thread_options.priority; let priority = self.priority;
let cpu_affinity = thread_options.cpu_affinity; let cpu_affinity = self.cpu_affinity;
Arc::new(Thread::new( Arc::new(Thread::new(
weak_task.clone(), weak_task.clone(),
kernel_thread, kernel_thread,
@ -69,45 +74,11 @@ pub fn create_new_kernel_task(mut thread_options: ThreadOptions) -> Arc<Task> {
}) })
} }
/// Options to create or spawn a new thread. /// Builds a new kernel thread and runs it immediately.
pub struct ThreadOptions { pub fn spawn(self) -> Arc<Thread> {
func: Option<Box<dyn Fn() + Send + Sync>>, let task = self.build();
priority: Priority, let thread = Thread::borrow_from_task(&task).clone();
cpu_affinity: CpuSet, thread.run();
} thread
impl ThreadOptions {
pub fn new<F>(func: F) -> Self
where
F: Fn() + Send + Sync + 'static,
{
let cpu_affinity = CpuSet::new_full();
Self {
func: Some(Box::new(func)),
priority: Priority::default(),
cpu_affinity,
}
}
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 {
self.priority = priority;
self
}
pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self {
self.cpu_affinity = cpu_affinity;
self
} }
} }

View File

@ -152,10 +152,22 @@ impl Thread {
&self.cpu_affinity &self.cpu_affinity
} }
/// Yields the execution to another thread.
///
/// This method will return once the current thread is scheduled again.
pub fn yield_now() { pub fn yield_now() {
Task::yield_now() Task::yield_now()
} }
/// Joins the execution of the thread.
///
/// This method will return after the thread exits.
pub fn join(&self) {
while !self.is_exited() {
Self::yield_now();
}
}
/// Returns the associated data. /// Returns the associated data.
pub fn data(&self) -> &(dyn Send + Sync + Any) { pub fn data(&self) -> &(dyn Send + Sync + Any) {
&*self.data &*self.data

View File

@ -11,7 +11,7 @@ use super::worker_pool::WorkerPool;
use crate::{ use crate::{
prelude::*, prelude::*,
sched::priority::{Priority, PriorityRange}, sched::priority::{Priority, PriorityRange},
thread::kernel_thread::{create_new_kernel_task, ThreadOptions}, thread::kernel_thread::ThreadOptions,
Thread, Thread,
}; };
@ -56,11 +56,10 @@ impl Worker {
// FIXME: remove the use of real-time priority. // FIXME: remove the use of real-time priority.
priority = Priority::new(PriorityRange::new(0)); priority = Priority::new(PriorityRange::new(0));
} }
let bound_task = create_new_kernel_task( let bound_task = ThreadOptions::new(task_fn)
ThreadOptions::new(task_fn)
.cpu_affinity(cpu_affinity) .cpu_affinity(cpu_affinity)
.priority(priority), .priority(priority)
); .build();
Self { Self {
worker_pool, worker_pool,
bound_task, bound_task,

View File

@ -17,7 +17,7 @@ use super::{simple_scheduler::SimpleScheduler, worker::Worker, WorkItem, WorkPri
use crate::{ use crate::{
prelude::*, prelude::*,
sched::priority::{Priority, PriorityRange}, sched::priority::{Priority, PriorityRange},
thread::kernel_thread::{create_new_kernel_task, ThreadOptions}, thread::kernel_thread::ThreadOptions,
Thread, Thread,
}; };
@ -246,11 +246,10 @@ impl Monitor {
WorkPriority::High => Priority::new(PriorityRange::new(0)), WorkPriority::High => Priority::new(PriorityRange::new(0)),
WorkPriority::Normal => Priority::default(), WorkPriority::Normal => Priority::default(),
}; };
let bound_task = create_new_kernel_task( let bound_task = ThreadOptions::new(task_fn)
ThreadOptions::new(task_fn)
.cpu_affinity(cpu_affinity) .cpu_affinity(cpu_affinity)
.priority(priority), .priority(priority)
); .build();
Self { Self {
worker_pool, worker_pool,
bound_task, bound_task,

View File

@ -215,7 +215,7 @@ impl TaskOptions {
Ok(new_task) Ok(new_task)
} }
/// Builds a new task and run it immediately. /// Builds a new task and runs it immediately.
pub fn spawn(self) -> Result<Arc<Task>> { pub fn spawn(self) -> Result<Arc<Task>> {
let task = Arc::new(self.build()?); let task = Arc::new(self.build()?);
task.run(); task.run();