Make Pauser work in raw tasks

This commit is contained in:
Ruihan Li
2024-07-11 01:41:24 +08:00
committed by Tate, Hongliang Tian
parent 8f64a1cb90
commit ceb0ef67e1
7 changed files with 41 additions and 32 deletions

View File

@ -30,11 +30,20 @@ macro_rules! current {
}; };
} }
/// return current thread /// Returns the current thread.
///
/// # Panics
///
/// This macro will panic if the current task is not associated with a thread.
///
/// Except for unit tests, all tasks should be associated with threads. To write code that can be
/// called directly in unit tests, consider using [`Thread::current`] instead.
///
/// [`Thread::current`]: crate::thread::Thread::current
#[macro_export] #[macro_export]
macro_rules! current_thread { macro_rules! current_thread {
() => { () => {
$crate::thread::Thread::current() $crate::thread::Thread::current().expect("the current task is not associated with a thread")
}; };
} }

View File

@ -641,7 +641,7 @@ impl Process {
} }
pub fn current() -> Arc<Process> { pub fn current() -> Arc<Process> {
let current_thread = Thread::current(); let current_thread = current_thread!();
if let Some(posix_thread) = current_thread.as_posix_thread() { if let Some(posix_thread) = current_thread.as_posix_thread() {
posix_thread.process() posix_thread.process()
} else { } else {

View File

@ -18,14 +18,12 @@ use ostd::{
use super::Process; use super::Process;
use crate::{ use crate::{
prelude::*,
process::{ process::{
posix_thread::PosixThreadExt, posix_thread::PosixThreadExt,
signal::{constants::SIGALRM, signals::kernel::KernelSignal}, signal::{constants::SIGALRM, signals::kernel::KernelSignal},
}, },
thread::{ thread::work_queue::{submit_work_item, work_item::WorkItem},
work_queue::{submit_work_item, work_item::WorkItem},
Thread,
},
time::{ time::{
clocks::{ProfClock, RealTimeClock}, clocks::{ProfClock, RealTimeClock},
Timer, TimerManager, Timer, TimerManager,
@ -38,7 +36,7 @@ use crate::{
/// invoke the callbacks of expired timers which are based on the updated /// invoke the callbacks of expired timers which are based on the updated
/// CPU clock. /// CPU clock.
fn update_cpu_time() { fn update_cpu_time() {
let current_thread = Thread::current(); let current_thread = current_thread!();
if let Some(posix_thread) = current_thread.as_posix_thread() { if let Some(posix_thread) = current_thread.as_posix_thread() {
let process = posix_thread.process(); let process = posix_thread.process();
let timer_manager = process.timer_manager(); let timer_manager = process.timer_manager();

View File

@ -123,9 +123,9 @@ impl Pauser {
where where
F: FnMut() -> Option<R>, F: FnMut() -> Option<R>,
{ {
let current_thread = current_thread!(); let current_thread = Thread::current();
let sig_queue_waiter = let sig_queue_waiter =
SigObserverRegistrar::new(&current_thread, self.sig_mask, self.clone()); SigObserverRegistrar::new(current_thread.as_ref(), self.sig_mask, self.clone());
let cond = || { let cond = || {
if let Some(res) = cond() { if let Some(res) = cond() {
@ -174,8 +174,12 @@ enum SigObserverRegistrar<'a> {
} }
impl<'a> SigObserverRegistrar<'a> { impl<'a> SigObserverRegistrar<'a> {
fn new(current_thread: &'a Arc<Thread>, sig_mask: SigMask, pauser: Arc<Pauser>) -> Self { fn new(
let Some(thread) = current_thread.as_posix_thread() else { current_thread: Option<&'a Arc<Thread>>,
sig_mask: SigMask,
pauser: Arc<Pauser>,
) -> Self {
let Some(thread) = current_thread.and_then(|thread| thread.as_posix_thread()) else {
return Self::KernelThread; return Self::KernelThread;
}; };
@ -281,19 +285,17 @@ 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 thread1 = Thread::spawn_kernel_thread(ThreadOptions::new(move || { let thread = Thread::spawn_kernel_thread(ThreadOptions::new(move || {
pauser
.pause_until(|| boolean.load(Ordering::Relaxed).then_some(()))
.unwrap();
}));
let thread2 = Thread::spawn_kernel_thread(ThreadOptions::new(move || {
Thread::yield_now(); Thread::yield_now();
boolean_cloned.store(true, Ordering::Relaxed); boolean_cloned.store(true, Ordering::Relaxed);
pauser_cloned.resume_all(); pauser_cloned.resume_all();
})); }));
thread1.join(); pauser
thread2.join(); .pause_until(|| boolean.load(Ordering::Relaxed).then_some(()))
.unwrap();
thread.join();
} }
} }

View File

@ -9,7 +9,7 @@ use super::SyscallReturn;
use crate::{ use crate::{
prelude::*, prelude::*,
process::{posix_thread::PosixThreadExt, process_table}, process::{posix_thread::PosixThreadExt, process_table},
thread::{thread_table, Thread}, thread::thread_table,
time::{ time::{
clockid_t, clockid_t,
clocks::{ clocks::{
@ -121,7 +121,7 @@ pub fn read_clock(clockid: clockid_t) -> Result<Duration> {
Ok(process.prof_clock().read_time()) Ok(process.prof_clock().read_time())
} }
ClockId::CLOCK_THREAD_CPUTIME_ID => { ClockId::CLOCK_THREAD_CPUTIME_ID => {
let thread = Thread::current(); let thread = current_thread!();
Ok(thread.as_posix_thread().unwrap().prof_clock().read_time()) Ok(thread.as_posix_thread().unwrap().prof_clock().read_time())
} }
} }

View File

@ -20,7 +20,6 @@ use crate::{
thread::{ thread::{
thread_table, thread_table,
work_queue::{submit_work_item, work_item::WorkItem}, work_queue::{submit_work_item, work_item::WorkItem},
Thread,
}, },
time::{ time::{
clockid_t, clockid_t,
@ -113,7 +112,7 @@ pub fn sys_timer_create(
match clock_id { match clock_id {
ClockId::CLOCK_PROCESS_CPUTIME_ID => process_timer_manager.create_prof_timer(func), ClockId::CLOCK_PROCESS_CPUTIME_ID => process_timer_manager.create_prof_timer(func),
ClockId::CLOCK_THREAD_CPUTIME_ID => { ClockId::CLOCK_THREAD_CPUTIME_ID => {
let current_thread = Thread::current(); let current_thread = current_thread!();
current_thread current_thread
.as_posix_thread() .as_posix_thread()
.unwrap() .unwrap()

View File

@ -50,15 +50,16 @@ impl Thread {
} }
} }
pub fn current() -> Arc<Self> { /// Returns the current thread, or `None` if the current task is not associated with a thread.
let task = Task::current(); ///
let thread = task /// Except for unit tests, all tasks should be associated with threads. This method is useful
/// when writing code that can be called directly by unit tests. If this isn't the case,
/// consider using [`current_thread!`] instead.
pub fn current() -> Option<Arc<Self>> {
Task::current()
.data() .data()
.downcast_ref::<Weak<Thread>>() .downcast_ref::<Weak<Thread>>()?
.expect("[Internal Error] task data should points to weak<thread>");
thread
.upgrade() .upgrade()
.expect("[Internal Error] current thread cannot be None")
} }
pub(in crate::thread) fn task(&self) -> &Arc<Task> { pub(in crate::thread) fn task(&self) -> &Arc<Task> {