mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Fix the thread status ordering by limiting the API
This commit is contained in:
parent
55bf2c847c
commit
1b23182dcc
@ -71,7 +71,7 @@ pub fn tgkill(tid: Tid, tgid: Pid, signal: Option<UserSignal>, ctx: &Context) ->
|
|||||||
let thread = thread_table::get_thread(tid)
|
let thread = thread_table::get_thread(tid)
|
||||||
.ok_or_else(|| Error::with_message(Errno::ESRCH, "target thread does not exist"))?;
|
.ok_or_else(|| Error::with_message(Errno::ESRCH, "target thread does not exist"))?;
|
||||||
|
|
||||||
if thread.status().is_exited() {
|
if thread.is_exited() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
///
|
///
|
||||||
/// If the thread is not a POSIX thread, this method will panic.
|
/// If the thread is not a POSIX thread, this method will panic.
|
||||||
pub fn do_exit(thread: &Thread, posix_thread: &PosixThread, term_status: TermStatus) -> Result<()> {
|
pub fn do_exit(thread: &Thread, posix_thread: &PosixThread, term_status: TermStatus) -> Result<()> {
|
||||||
if thread.status().is_exited() {
|
if thread.is_exited() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
thread.exit();
|
thread.exit();
|
||||||
|
@ -277,7 +277,7 @@ impl PosixThread {
|
|||||||
let tasks = process.tasks().lock();
|
let tasks = process.tasks().lock();
|
||||||
tasks
|
tasks
|
||||||
.iter()
|
.iter()
|
||||||
.all(|task| Thread::borrow_from_task(task).status().is_exited())
|
.all(|task| Thread::borrow_from_task(task).is_exited())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the read-only credentials of the thread.
|
/// Gets the read-only credentials of the thread.
|
||||||
|
@ -31,7 +31,6 @@ use crate::{
|
|||||||
get_current_userspace,
|
get_current_userspace,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{do_exit_group, TermStatus},
|
process::{do_exit_group, TermStatus},
|
||||||
thread::status::ThreadStatus,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait SignalContext {
|
pub trait SignalContext {
|
||||||
@ -107,20 +106,10 @@ pub fn handle_pending_signal(user_ctx: &mut UserContext, ctx: &Context) -> Resul
|
|||||||
}
|
}
|
||||||
SigDefaultAction::Ign => {}
|
SigDefaultAction::Ign => {}
|
||||||
SigDefaultAction::Stop => {
|
SigDefaultAction::Stop => {
|
||||||
let _ = ctx.thread.atomic_status().compare_exchange(
|
let _ = ctx.thread.stop();
|
||||||
ThreadStatus::Running,
|
|
||||||
ThreadStatus::Stopped,
|
|
||||||
Ordering::AcqRel,
|
|
||||||
Ordering::Relaxed,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
SigDefaultAction::Cont => {
|
SigDefaultAction::Cont => {
|
||||||
let _ = ctx.thread.atomic_status().compare_exchange(
|
let _ = ctx.thread.resume();
|
||||||
ThreadStatus::Stopped,
|
|
||||||
ThreadStatus::Running,
|
|
||||||
Ordering::AcqRel,
|
|
||||||
Ordering::Relaxed,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ impl KernelThreadExt for Thread {
|
|||||||
|
|
||||||
fn join(&self) {
|
fn join(&self) {
|
||||||
loop {
|
loop {
|
||||||
if self.status().is_exited() {
|
if self.is_exited() {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
|
@ -86,27 +86,59 @@ impl Thread {
|
|||||||
|
|
||||||
/// Runs this thread at once.
|
/// Runs this thread at once.
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
self.set_status(ThreadStatus::Running);
|
self.status.store(ThreadStatus::Running, Ordering::Release);
|
||||||
self.task.upgrade().unwrap().run();
|
self.task.upgrade().unwrap().run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the thread is exited.
|
||||||
|
pub fn is_exited(&self) -> bool {
|
||||||
|
self.status.load(Ordering::Acquire).is_exited()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the thread is stopped.
|
||||||
|
pub fn is_stopped(&self) -> bool {
|
||||||
|
self.status.load(Ordering::Acquire).is_stopped()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stops the thread if it is running.
|
||||||
|
///
|
||||||
|
/// If the previous status is not [`ThreadStatus::Running`], this function
|
||||||
|
/// returns [`Err`] with the previous state. Otherwise, it sets the status
|
||||||
|
/// to [`ThreadStatus::Stopped`] and returns [`Ok`] with the previous state.
|
||||||
|
///
|
||||||
|
/// This function only sets the status to [`ThreadStatus::Stopped`],
|
||||||
|
/// without initiating a reschedule.
|
||||||
|
pub fn stop(&self) -> core::result::Result<ThreadStatus, ThreadStatus> {
|
||||||
|
self.status.compare_exchange(
|
||||||
|
ThreadStatus::Running,
|
||||||
|
ThreadStatus::Stopped,
|
||||||
|
Ordering::AcqRel,
|
||||||
|
Ordering::Acquire,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resumes running the thread if it is stopped.
|
||||||
|
///
|
||||||
|
/// If the previous status is not [`ThreadStatus::Stopped`], this function
|
||||||
|
/// returns [`None`]. Otherwise, it sets the status to
|
||||||
|
/// [`ThreadStatus::Running`] and returns [`Some(())`].
|
||||||
|
///
|
||||||
|
/// This function only sets the status to [`ThreadStatus::Running`],
|
||||||
|
/// without initiating a reschedule.
|
||||||
|
pub fn resume(&self) -> Option<()> {
|
||||||
|
self.status
|
||||||
|
.compare_exchange(
|
||||||
|
ThreadStatus::Stopped,
|
||||||
|
ThreadStatus::Running,
|
||||||
|
Ordering::AcqRel,
|
||||||
|
Ordering::Acquire,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn exit(&self) {
|
pub(super) fn exit(&self) {
|
||||||
self.set_status(ThreadStatus::Exited);
|
self.status.store(ThreadStatus::Exited, Ordering::Release);
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the reference to the atomic status.
|
|
||||||
pub fn atomic_status(&self) -> &AtomicThreadStatus {
|
|
||||||
&self.status
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the reference to the atomic priority.
|
/// Returns the reference to the atomic priority.
|
||||||
@ -114,16 +146,6 @@ impl Thread {
|
|||||||
&self.priority
|
&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.
|
/// Returns the reference to the atomic CPU affinity.
|
||||||
pub fn atomic_cpu_affinity(&self) -> &AtomicCpuSet {
|
pub fn atomic_cpu_affinity(&self) -> &AtomicCpuSet {
|
||||||
&self.cpu_affinity
|
&self.cpu_affinity
|
||||||
|
@ -71,17 +71,17 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Arc<Thread>)
|
|||||||
ReturnReason::KernelEvent => {}
|
ReturnReason::KernelEvent => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
if current_thread.status().is_exited() {
|
if current_thread.is_exited() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
handle_pending_signal(user_ctx, &ctx).unwrap();
|
handle_pending_signal(user_ctx, &ctx).unwrap();
|
||||||
// If current is suspended, wait for a signal to wake up self
|
// If current is suspended, wait for a signal to wake up self
|
||||||
while current_thread.status().is_stopped() {
|
while current_thread.is_stopped() {
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
debug!("{} is suspended.", current_posix_thread.tid());
|
debug!("{} is suspended.", current_posix_thread.tid());
|
||||||
handle_pending_signal(user_ctx, &ctx).unwrap();
|
handle_pending_signal(user_ctx, &ctx).unwrap();
|
||||||
}
|
}
|
||||||
if current_thread.status().is_exited() {
|
if current_thread.is_exited() {
|
||||||
debug!("exit due to signal");
|
debug!("exit due to signal");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user