diff --git a/docs/src/kernel/linux-compatibility.md b/docs/src/kernel/linux-compatibility.md index 250384c6b..81d10031c 100644 --- a/docs/src/kernel/linux-compatibility.md +++ b/docs/src/kernel/linux-compatibility.md @@ -85,7 +85,7 @@ provided by Linux on x86-64 architecture. | 62 | kill | ✅ | | 63 | uname | ✅ | | 64 | semget | ✅ | -| 65 | semop | ❌ | +| 65 | semop | ✅ | | 66 | semctl | ❌ | | 67 | shmdt | ❌ | | 68 | msgget | ❌ | @@ -240,7 +240,7 @@ provided by Linux on x86-64 architecture. | 217 | getdents64 | ✅ | | 218 | set_tid_address | ✅ | | 219 | restart_syscall | ❌ | -| 220 | semtimedop | ❌ | +| 220 | semtimedop | ✅ | | 221 | fadvise64 | ❌ | | 222 | timer_create | ✅ | | 223 | timer_settime | ✅ | diff --git a/kernel/aster-nix/src/syscall/arch/x86.rs b/kernel/aster-nix/src/syscall/arch/x86.rs index d8eeaed0c..ca03be57e 100644 --- a/kernel/aster-nix/src/syscall/arch/x86.rs +++ b/kernel/aster-nix/src/syscall/arch/x86.rs @@ -90,6 +90,7 @@ use crate::syscall::{ sched_yield::sys_sched_yield, select::sys_select, semget::sys_semget, + semop::{sys_semop, sys_semtimedop}, sendfile::sys_sendfile, sendmsg::sys_sendmsg, sendto::sys_sendto, @@ -192,6 +193,7 @@ impl_syscall_nums_and_dispatch_fn! { SYS_KILL = 62 => sys_kill(args[..2]); SYS_UNAME = 63 => sys_uname(args[..1]); SYS_SEMGET = 64 => sys_semget(args[..3]); + SYS_SEMOP = 65 => sys_semop(args[..3]); SYS_FCNTL = 72 => sys_fcntl(args[..3]); SYS_FLOCK = 73 => sys_flock(args[..2]); SYS_FSYNC = 74 => sys_fsync(args[..1]); @@ -263,6 +265,7 @@ impl_syscall_nums_and_dispatch_fn! { SYS_EPOLL_CREATE = 213 => sys_epoll_create(args[..1]); SYS_GETDENTS64 = 217 => sys_getdents64(args[..3]); SYS_SET_TID_ADDRESS = 218 => sys_set_tid_address(args[..1]); + SYS_SEMTIMEDOP = 220 => sys_semtimedop(args[..4]); SYS_TIMER_CREATE = 222 => sys_timer_create(args[..3]); SYS_TIMER_SETTIME = 223 => sys_timer_settime(args[..4]); SYS_TIMER_GETTIME = 224 => sys_timer_gettime(args[..2]); diff --git a/kernel/aster-nix/src/syscall/mod.rs b/kernel/aster-nix/src/syscall/mod.rs index 876e0f70b..1235f5678 100644 --- a/kernel/aster-nix/src/syscall/mod.rs +++ b/kernel/aster-nix/src/syscall/mod.rs @@ -97,6 +97,7 @@ mod sched_getaffinity; mod sched_yield; mod select; mod semget; +mod semop; mod sendfile; mod sendmsg; mod sendto; diff --git a/kernel/aster-nix/src/syscall/semop.rs b/kernel/aster-nix/src/syscall/semop.rs new file mode 100644 index 000000000..81115ec21 --- /dev/null +++ b/kernel/aster-nix/src/syscall/semop.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MPL-2.0 + +use core::time::Duration; + +use super::SyscallReturn; +use crate::{ + ipc::semaphore::system_v::{ + sem::{sem_op, SemBuf}, + sem_set::{check_sem, SEMOPM}, + PermissionMode, + }, + prelude::*, + time::timespec_t, +}; + +pub fn sys_semop(sem_id: i32, tsops: Vaddr, nsops: usize, _ctx: &Context) -> Result { + debug!( + "[sys_semop] sem_id = {:?}, tsops_vaddr = {:x?}, nsops = {:?}", + sem_id, tsops, nsops + ); + do_sys_semtimedop(sem_id, tsops, nsops, None) +} + +pub fn sys_semtimedop( + sem_id: i32, + tsops: Vaddr, + nsops: usize, + timeout: Vaddr, + ctx: &Context, +) -> Result { + debug!( + "[sys_semtimedop] sem_id = {:?}, tsops_vaddr = {:x?}, nsops = {:?}, timeout_vaddr = {:x?}", + sem_id, tsops, nsops, timeout + ); + + let timeout = if timeout == 0 { + None + } else { + Some(Duration::try_from( + ctx.get_user_space().read_val::(timeout)?, + )?) + }; + + do_sys_semtimedop(sem_id, tsops, nsops, timeout) +} + +fn do_sys_semtimedop( + sem_id: i32, + tsops: Vaddr, + nsops: usize, + timeout: Option, +) -> Result { + if sem_id <= 0 || nsops == 0 { + return_errno!(Errno::EINVAL); + } + if nsops > SEMOPM { + return_errno!(Errno::E2BIG); + } + + for i in 0..nsops { + let sem_buf = + CurrentUserSpace::get().read_val::(tsops + size_of::() * i)?; + if sem_buf.sem_op() != 0 { + check_sem(sem_id, None, PermissionMode::ALTER)?; + } + + sem_op(sem_id, sem_buf, timeout)?; + } + + Ok(SyscallReturn::Return(0)) +}