Implement semop and semtimedop syscall

This commit is contained in:
Yuke Peng
2024-08-10 18:51:53 +08:00
committed by Tate, Hongliang Tian
parent 4530253a99
commit 9d83e76931
4 changed files with 77 additions and 2 deletions

View File

@ -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 | ✅ |

View File

@ -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]);

View File

@ -97,6 +97,7 @@ mod sched_getaffinity;
mod sched_yield;
mod select;
mod semget;
mod semop;
mod sendfile;
mod sendmsg;
mod sendto;

View File

@ -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<SyscallReturn> {
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<SyscallReturn> {
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::<timespec_t>(timeout)?,
)?)
};
do_sys_semtimedop(sem_id, tsops, nsops, timeout)
}
fn do_sys_semtimedop(
sem_id: i32,
tsops: Vaddr,
nsops: usize,
timeout: Option<Duration>,
) -> Result<SyscallReturn> {
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::<SemBuf>(tsops + size_of::<SemBuf>() * 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))
}