diff --git a/framework/aster-frame/src/task/processor.rs b/framework/aster-frame/src/task/processor.rs index adc6b1ed8..a29562bb8 100644 --- a/framework/aster-frame/src/task/processor.rs +++ b/framework/aster-frame/src/task/processor.rs @@ -61,14 +61,15 @@ pub fn schedule() { } } -pub fn preempt() { +// TODO: This interface of this method is error prone. +// The method takes an argument for the current task to optimize its efficiency, +// but the argument provided by the caller may not be the current task, really. +// Thus, this method should be removed or reworked in the future. +pub fn preempt(task: &Arc) { // TODO: Refactor `preempt` and `schedule` // after the Atomic mode and `might_break` is enabled. - let Some(curr_task) = current_task() else { - return; - }; let mut scheduler = GLOBAL_SCHEDULER.lock_irq_disabled(); - if !scheduler.should_preempt(&curr_task) { + if !scheduler.should_preempt(task) { return; } let Some(next_task) = scheduler.dequeue() else { diff --git a/kernel/aster-nix/src/process/signal/mod.rs b/kernel/aster-nix/src/process/signal/mod.rs index c2dd30356..02d11d378 100644 --- a/kernel/aster-nix/src/process/signal/mod.rs +++ b/kernel/aster-nix/src/process/signal/mod.rs @@ -30,17 +30,20 @@ use super::posix_thread::{PosixThread, PosixThreadExt}; use crate::{ prelude::*, process::{do_exit_group, TermStatus}, + thread::Thread, util::{write_bytes_to_user, write_val_to_user}, }; -/// Handle pending signal for current process -pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> { - let current = current!(); - let current_thread = current_thread!(); - +// TODO: This interface of this method is error prone. +// The method takes an argument for the current thread to optimize its efficiency. +/// Handle pending signal for current process. +pub fn handle_pending_signal( + context: &mut UserContext, + current_thread: &Arc, +) -> Result<()> { // We first deal with signal in current thread, then signal in current process. + let posix_thread = current_thread.as_posix_thread().unwrap(); let signal = { - let posix_thread = current_thread.as_posix_thread().unwrap(); let sig_mask = *posix_thread.sig_mask().lock(); if let Some(signal) = posix_thread.dequeue_signal(&sig_mask) { signal @@ -51,6 +54,7 @@ pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> { let sig_num = signal.num(); trace!("sig_num = {:?}, sig_name = {}", sig_num, sig_num.sig_name()); + let current = posix_thread.process(); let sig_action = current.sig_dispositions().lock().get(sig_num); trace!("sig action: {:x?}", sig_action); match sig_action { diff --git a/kernel/aster-nix/src/thread/mod.rs b/kernel/aster-nix/src/thread/mod.rs index e2ddaa36d..8ba33c57a 100644 --- a/kernel/aster-nix/src/thread/mod.rs +++ b/kernel/aster-nix/src/thread/mod.rs @@ -61,6 +61,10 @@ impl Thread { .expect("[Internal Error] current thread cannot be None") } + pub(in crate::thread) fn task(&self) -> &Arc { + &self.task + } + /// Run this thread at once. pub fn run(&self) { self.status.lock().set_running(); diff --git a/kernel/aster-nix/src/thread/task.rs b/kernel/aster-nix/src/thread/task.rs index 47f5c4c80..c39a32ec1 100644 --- a/kernel/aster-nix/src/thread/task.rs +++ b/kernel/aster-nix/src/thread/task.rs @@ -15,8 +15,11 @@ use crate::{ /// create new task with userspace and parent process pub fn create_new_user_task(user_space: Arc, thread_ref: Weak) -> Arc { fn user_task_entry() { - let cur = Task::current(); - let user_space = cur.user_space().expect("user task should have user space"); + let current_thread = current_thread!(); + let current_task = current_thread.task(); + let user_space = current_task + .user_space() + .expect("user task should have user space"); let mut user_mode = UserMode::new(user_space); debug!( "[Task entry] rip = 0x{:x}", @@ -30,17 +33,17 @@ pub fn create_new_user_task(user_space: Arc, thread_ref: Weak "[Task entry] rax = 0x{:x}", user_mode.context().syscall_ret() ); + loop { let user_event = user_mode.execute(); let context = user_mode.context_mut(); // handle user event: handle_user_event(user_event, context); - let current_thread = current_thread!(); // should be do this comparison before handle signal? if current_thread.status().lock().is_exited() { break; } - handle_pending_signal(context).unwrap(); + handle_pending_signal(context, ¤t_thread).unwrap(); if current_thread.status().lock().is_exited() { debug!("exit due to signal"); break; @@ -49,14 +52,14 @@ pub fn create_new_user_task(user_space: Arc, thread_ref: Weak while current_thread.status().lock().is_stopped() { Thread::yield_now(); debug!("{} is suspended.", current_thread.tid()); - handle_pending_signal(context).unwrap(); + handle_pending_signal(context, ¤t_thread).unwrap(); } // a preemption point after handling user event. - preempt(); + preempt(current_task); } debug!("exit user loop"); // FIXME: This is a work around: exit in kernel task entry may be not called. Why this will happen? - Task::current().exit(); + current_task.exit(); } TaskOptions::new(user_task_entry)