diff --git a/docs/src/kernel/linux-compatibility.md b/docs/src/kernel/linux-compatibility.md index b668625c9..42a2e7e6f 100644 --- a/docs/src/kernel/linux-compatibility.md +++ b/docs/src/kernel/linux-compatibility.md @@ -271,8 +271,8 @@ provided by Linux on x86-64 architecture. | 248 | add_key | ❌ | | 249 | request_key | ❌ | | 250 | keyctl | ❌ | -| 251 | ioprio_set | ❌ | -| 252 | ioprio_get | ❌ | +| 251 | ioprio_set | ✅ | +| 252 | ioprio_get | ✅ | | 253 | inotify_init | ❌ | | 254 | inotify_add_watch | ❌ | | 255 | inotify_rm_watch | ❌ | diff --git a/kernel/src/process/posix_thread/builder.rs b/kernel/src/process/posix_thread/builder.rs index d50034087..ff24c52d9 100644 --- a/kernel/src/process/posix_thread/builder.rs +++ b/kernel/src/process/posix_thread/builder.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +use core::sync::atomic::AtomicU32; + use ostd::{ cpu::{ context::{FpuContext, UserContext}, @@ -150,6 +152,7 @@ impl PosixThreadBuilder { prof_clock, virtual_timer_manager, prof_timer_manager, + io_priority: AtomicU32::new(0), } }; diff --git a/kernel/src/process/posix_thread/mod.rs b/kernel/src/process/posix_thread/mod.rs index 042a3f963..fb3667bd6 100644 --- a/kernel/src/process/posix_thread/mod.rs +++ b/kernel/src/process/posix_thread/mod.rs @@ -76,6 +76,9 @@ pub struct PosixThread { /// A manager that manages timers based on the profiling clock of the current thread. prof_timer_manager: Arc, + + /// I/O Scheduling priority value + io_priority: AtomicU32, } impl PosixThread { @@ -308,6 +311,11 @@ impl PosixThread { )); self.credentials.dup().restrict() } + + /// Returns the I/O priority value of the thread. + pub fn io_priority(&self) -> &AtomicU32 { + &self.io_priority + } } static POSIX_TID_ALLOCATOR: AtomicU32 = AtomicU32::new(1); diff --git a/kernel/src/syscall/arch/riscv.rs b/kernel/src/syscall/arch/riscv.rs index 8e9bb4588..215ddd997 100644 --- a/kernel/src/syscall/arch/riscv.rs +++ b/kernel/src/syscall/arch/riscv.rs @@ -29,6 +29,7 @@ use super::{ flock::sys_flock, fsync::{sys_fdatasync, sys_fsync}, futex::sys_futex, + get_ioprio::sys_ioprio_get, get_priority::sys_get_priority, getcpu::sys_getcpu, getcwd::sys_getcwd, @@ -101,6 +102,7 @@ use super::{ sendfile::sys_sendfile, sendmsg::sys_sendmsg, sendto::sys_sendto, + set_ioprio::sys_ioprio_set, set_priority::sys_set_priority, set_robust_list::sys_set_robust_list, set_tid_address::sys_set_tid_address, @@ -154,6 +156,8 @@ impl_syscall_nums_and_dispatch_fn! { SYS_DUP3 = 24 => sys_dup3(args[..3]); SYS_FCNTL = 25 => sys_fcntl(args[..3]); SYS_IOCTL = 29 => sys_ioctl(args[..3]); + SYS_IOPRIO_SET = 30 => sys_ioprio_set(args[..3]); + SYS_IOPRIO_GET = 31 => sys_ioprio_get(args[..2]); SYS_FLOCK = 32 => sys_flock(args[..2]); SYS_MKNODAT = 33 => sys_mknodat(args[..4]); SYS_MKDIRAT = 34 => sys_mkdirat(args[..3]); diff --git a/kernel/src/syscall/arch/x86.rs b/kernel/src/syscall/arch/x86.rs index b25a560e7..21a83d10e 100644 --- a/kernel/src/syscall/arch/x86.rs +++ b/kernel/src/syscall/arch/x86.rs @@ -35,6 +35,7 @@ use super::{ fork::{sys_fork, sys_vfork}, fsync::{sys_fdatasync, sys_fsync}, futex::sys_futex, + get_ioprio::sys_ioprio_get, get_priority::sys_get_priority, getcpu::sys_getcpu, getcwd::sys_getcwd, @@ -117,6 +118,7 @@ use super::{ sendfile::sys_sendfile, sendmsg::sys_sendmsg, sendto::sys_sendto, + set_ioprio::sys_ioprio_set, set_priority::sys_set_priority, set_robust_list::sys_set_robust_list, set_tid_address::sys_set_tid_address, @@ -335,6 +337,8 @@ impl_syscall_nums_and_dispatch_fn! { SYS_TGKILL = 234 => sys_tgkill(args[..3]); SYS_UTIMES = 235 => sys_utimes(args[..2]); SYS_WAITID = 247 => sys_waitid(args[..5]); + SYS_IOPRIO_SET = 251 => sys_ioprio_set(args[..3]); + SYS_IOPRIO_GET = 252 => sys_ioprio_get(args[..2]); SYS_OPENAT = 257 => sys_openat(args[..4]); SYS_MKDIRAT = 258 => sys_mkdirat(args[..3]); SYS_MKNODAT = 259 => sys_mknodat(args[..4]); diff --git a/kernel/src/syscall/get_ioprio.rs b/kernel/src/syscall/get_ioprio.rs new file mode 100644 index 000000000..9b7e83b89 --- /dev/null +++ b/kernel/src/syscall/get_ioprio.rs @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::{sync::Arc, vec::Vec}; +use core::sync::atomic::Ordering; + +use super::SyscallReturn; +use crate::{ + prelude::*, + process::{posix_thread::AsPosixThread, ProcessGroup}, + thread::Thread, +}; + +#[expect(dead_code)] +pub(super) enum IoPrioWho { + Thread(Arc), + ProcessGroup(Arc), + /// The threads belong to the same user + User(Vec>), +} + +impl IoPrioWho { + const IOPRIO_WHO_PROCESS: u32 = 1; + const IOPRIO_WHO_PGRP: u32 = 2; + const IOPRIO_WHO_USER: u32 = 3; + + pub(super) fn from_which_and_who(which: u32, who: u32, ctx: &Context) -> Result { + match which { + Self::IOPRIO_WHO_PROCESS => { + // In Linux, IOPRIO_WHO_PROCESS identifies a single thread by its TID + let target_tid = if who == 0 { + ctx.posix_thread.tid() + } else { + who + }; + + let thread = crate::process::posix_thread::thread_table::get_thread(target_tid) + .ok_or_else(|| Error::new(Errno::ESRCH))?; + Ok(Self::Thread(thread)) + } + Self::IOPRIO_WHO_PGRP => { + // TODO: Implement process group support + return_errno!(Errno::EINVAL); + } + Self::IOPRIO_WHO_USER => { + // TODO: Implement user support + return_errno!(Errno::EINVAL); + } + _ => return_errno!(Errno::EINVAL), + } + } +} + +pub fn sys_ioprio_get(which: u32, who: u32, ctx: &Context) -> Result { + debug!("which = {}, who = {}", which, who); + + let ioprio_who = IoPrioWho::from_which_and_who(which, who, ctx)?; + + match ioprio_who { + IoPrioWho::Thread(thread) => { + let prio = thread + .as_posix_thread() + .unwrap() + .io_priority() + .load(Ordering::Relaxed); + Ok(SyscallReturn::Return(prio as _)) + } + IoPrioWho::ProcessGroup(_) => { + // TODO: Implement process group support + return_errno!(Errno::EINVAL); + } + IoPrioWho::User(_) => { + // TODO: Implement user support + return_errno!(Errno::EINVAL); + } + } +} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index cdb57f1a8..11a95fcf0 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -44,6 +44,7 @@ mod flock; mod fork; mod fsync; mod futex; +mod get_ioprio; mod get_priority; mod getcpu; mod getcwd; @@ -125,6 +126,7 @@ mod semop; mod sendfile; mod sendmsg; mod sendto; +mod set_ioprio; mod set_priority; mod set_robust_list; mod set_tid_address; diff --git a/kernel/src/syscall/set_ioprio.rs b/kernel/src/syscall/set_ioprio.rs new file mode 100644 index 000000000..4c4e8473f --- /dev/null +++ b/kernel/src/syscall/set_ioprio.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MPL-2.0 + +use core::sync::atomic::Ordering; + +use super::{get_ioprio::IoPrioWho, SyscallReturn}; +use crate::{prelude::*, process::posix_thread::AsPosixThread}; + +pub fn sys_ioprio_set(which: u32, who: u32, ioprio: u32, ctx: &Context) -> Result { + debug!("which = {}, who = {}, ioprio = {}", which, who, ioprio); + + let ioprio_who = IoPrioWho::from_which_and_who(which, who, ctx)?; + + match ioprio_who { + IoPrioWho::Thread(thread) => { + thread + .as_posix_thread() + .unwrap() + .io_priority() + .store(ioprio, Ordering::Relaxed); + Ok(SyscallReturn::Return(0)) + } + IoPrioWho::ProcessGroup(_) => { + // TODO: Implement process group support + return_errno!(Errno::EINVAL); + } + IoPrioWho::User(_) => { + // TODO: Implement user support + return_errno!(Errno::EINVAL); + } + } +} diff --git a/test/src/syscall/ltp/testcases/all.txt b/test/src/syscall/ltp/testcases/all.txt index cffd5623c..56cdc5008 100644 --- a/test/src/syscall/ltp/testcases/all.txt +++ b/test/src/syscall/ltp/testcases/all.txt @@ -651,9 +651,9 @@ getxattr01 # iopl01 # iopl02 -# ioprio_get01 -# ioprio_set01 -# ioprio_set02 +ioprio_get01 +ioprio_set01 +ioprio_set02 # ioprio_set03 # io_cancel01