asterinas/kernel/src/thread/mod.rs

144 lines
3.6 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
2022-12-15 06:53:43 +00:00
//! Posix thread implementation
2024-09-12 04:48:33 +00:00
use core::sync::atomic::Ordering;
2022-12-15 06:53:43 +00:00
use ostd::{
cpu::{AtomicCpuSet, CpuSet},
task::Task,
};
2022-12-15 06:53:43 +00:00
use self::status::{AtomicThreadStatus, ThreadStatus};
use crate::{
prelude::*,
sched::priority::{AtomicPriority, Priority},
};
2022-12-20 06:12:22 +00:00
pub mod exception;
pub mod kernel_thread;
pub mod oops;
2022-12-20 06:12:22 +00:00
pub mod status;
2022-12-15 06:53:43 +00:00
pub mod task;
pub mod work_queue;
2022-12-15 06:53:43 +00:00
pub type Tid = u32;
2022-12-15 06:53:43 +00:00
/// A thread is a wrapper on top of task.
pub struct Thread {
2022-12-20 06:12:22 +00:00
// immutable part
2022-12-15 06:53:43 +00:00
/// Low-level info
task: Weak<Task>,
2022-12-20 06:12:22 +00:00
/// Data: Posix thread info/Kernel thread Info
data: Box<dyn Send + Sync + Any>,
// mutable part
/// Thread status
status: AtomicThreadStatus,
/// Thread priority
priority: AtomicPriority,
/// Thread CPU affinity
cpu_affinity: AtomicCpuSet,
2022-12-15 06:53:43 +00:00
}
impl Thread {
2022-12-20 06:12:22 +00:00
/// Never call these function directly
pub fn new(
task: Weak<Task>,
data: impl Send + Sync + Any,
status: ThreadStatus,
priority: Priority,
cpu_affinity: CpuSet,
) -> Self {
2022-12-20 06:12:22 +00:00
Thread {
task,
data: Box::new(data),
status: AtomicThreadStatus::new(status),
priority: AtomicPriority::new(priority),
cpu_affinity: AtomicCpuSet::new(cpu_affinity),
2022-12-20 06:12:22 +00:00
}
2022-12-15 06:53:43 +00:00
}
/// Returns the current thread.
2024-07-10 17:41:24 +00:00
///
/// This function returns `None` if the current task is not associated with
/// a thread, or if called within the bootstrap context.
2024-07-10 17:41:24 +00:00
pub fn current() -> Option<Arc<Self>> {
Task::current()?
2022-12-15 06:53:43 +00:00
.data()
.downcast_ref::<Arc<Thread>>()
.cloned()
2022-12-15 06:53:43 +00:00
}
/// Returns the task associated with this thread.
pub fn task(&self) -> Arc<Task> {
self.task.upgrade().unwrap()
}
/// Gets the Thread from task's data.
///
/// # Panics
///
/// This method panics if the task is not a thread.
pub fn borrow_from_task(task: &Task) -> &Arc<Self> {
task.data().downcast_ref::<Arc<Thread>>().unwrap()
}
/// Runs this thread at once.
2022-12-15 06:53:43 +00:00
pub fn run(&self) {
self.set_status(ThreadStatus::Running);
self.task.upgrade().unwrap().run();
2022-12-15 06:53:43 +00:00
}
pub(super) fn exit(&self) {
self.set_status(ThreadStatus::Exited);
2022-12-20 06:12:22 +00:00
}
/// Returns the reference to the atomic status.
pub fn atomic_status(&self) -> &AtomicThreadStatus {
&self.status
2023-09-01 03:40:22 +00:00
}
/// Returns the current status.
pub fn status(&self) -> ThreadStatus {
self.status.load(Ordering::Acquire)
}
/// Updates the status with the new value.
pub fn set_status(&self, new_status: ThreadStatus) {
self.status.store(new_status, Ordering::Release);
2022-12-20 06:12:22 +00:00
}
/// Returns the reference to the atomic priority.
pub fn atomic_priority(&self) -> &AtomicPriority {
&self.priority
}
/// Returns the current priority.
pub fn priority(&self) -> Priority {
self.priority.load(Ordering::Relaxed)
}
/// Updates the priority with the new value.
pub fn set_priority(&self, new_priority: Priority) {
self.priority.store(new_priority, Ordering::Relaxed)
}
/// Returns the reference to the atomic CPU affinity.
pub fn atomic_cpu_affinity(&self) -> &AtomicCpuSet {
&self.cpu_affinity
}
2022-12-15 06:53:43 +00:00
pub fn yield_now() {
Task::yield_now()
}
2022-12-20 06:12:22 +00:00
/// Returns the associated data.
///
/// The return type must be borrowed box, otherwise the `downcast_ref` will fail.
2023-09-04 03:04:42 +00:00
#[allow(clippy::borrowed_box)]
2022-12-20 06:12:22 +00:00
pub fn data(&self) -> &Box<dyn Send + Sync + Any> {
&self.data
}
}