mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Implement semctl syscall
This commit is contained in:
parent
9d83e76931
commit
60ef523aaf
@ -86,7 +86,7 @@ provided by Linux on x86-64 architecture.
|
|||||||
| 63 | uname | ✅ |
|
| 63 | uname | ✅ |
|
||||||
| 64 | semget | ✅ |
|
| 64 | semget | ✅ |
|
||||||
| 65 | semop | ✅ |
|
| 65 | semop | ✅ |
|
||||||
| 66 | semctl | ❌ |
|
| 66 | semctl | ✅ |
|
||||||
| 67 | shmdt | ❌ |
|
| 67 | shmdt | ❌ |
|
||||||
| 68 | msgget | ❌ |
|
| 68 | msgget | ❌ |
|
||||||
| 69 | msgsnd | ❌ |
|
| 69 | msgsnd | ❌ |
|
||||||
|
@ -89,6 +89,7 @@ use crate::syscall::{
|
|||||||
sched_getaffinity::sys_sched_getaffinity,
|
sched_getaffinity::sys_sched_getaffinity,
|
||||||
sched_yield::sys_sched_yield,
|
sched_yield::sys_sched_yield,
|
||||||
select::sys_select,
|
select::sys_select,
|
||||||
|
semctl::sys_semctl,
|
||||||
semget::sys_semget,
|
semget::sys_semget,
|
||||||
semop::{sys_semop, sys_semtimedop},
|
semop::{sys_semop, sys_semtimedop},
|
||||||
sendfile::sys_sendfile,
|
sendfile::sys_sendfile,
|
||||||
@ -194,6 +195,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_UNAME = 63 => sys_uname(args[..1]);
|
SYS_UNAME = 63 => sys_uname(args[..1]);
|
||||||
SYS_SEMGET = 64 => sys_semget(args[..3]);
|
SYS_SEMGET = 64 => sys_semget(args[..3]);
|
||||||
SYS_SEMOP = 65 => sys_semop(args[..3]);
|
SYS_SEMOP = 65 => sys_semop(args[..3]);
|
||||||
|
SYS_SEMCTL = 66 => sys_semctl(args[..4]);
|
||||||
SYS_FCNTL = 72 => sys_fcntl(args[..3]);
|
SYS_FCNTL = 72 => sys_fcntl(args[..3]);
|
||||||
SYS_FLOCK = 73 => sys_flock(args[..2]);
|
SYS_FLOCK = 73 => sys_flock(args[..2]);
|
||||||
SYS_FSYNC = 74 => sys_fsync(args[..1]);
|
SYS_FSYNC = 74 => sys_fsync(args[..1]);
|
||||||
|
@ -96,6 +96,7 @@ mod rt_sigsuspend;
|
|||||||
mod sched_getaffinity;
|
mod sched_getaffinity;
|
||||||
mod sched_yield;
|
mod sched_yield;
|
||||||
mod select;
|
mod select;
|
||||||
|
mod semctl;
|
||||||
mod semget;
|
mod semget;
|
||||||
mod semop;
|
mod semop;
|
||||||
mod sendfile;
|
mod sendfile;
|
||||||
|
121
kernel/aster-nix/src/syscall/semctl.rs
Normal file
121
kernel/aster-nix/src/syscall/semctl.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use crate::{
|
||||||
|
ipc::{
|
||||||
|
semaphore::system_v::{
|
||||||
|
sem_set::{check_sem, sem_sets, sem_sets_mut, SemaphoreSet},
|
||||||
|
PermissionMode,
|
||||||
|
},
|
||||||
|
IpcControlCmd,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
process::Pid,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn sys_semctl(
|
||||||
|
semid: i32,
|
||||||
|
semnum: i32,
|
||||||
|
cmd: i32,
|
||||||
|
arg: Vaddr,
|
||||||
|
ctx: &Context,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
|
if semid <= 0 || semnum < 0 {
|
||||||
|
return_errno!(Errno::EINVAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd = IpcControlCmd::try_from(cmd)?;
|
||||||
|
debug!(
|
||||||
|
"[sys_semctl] semid = {}, semnum = {}, cmd = {:?}, arg = {:x}",
|
||||||
|
semid, semnum, cmd, arg
|
||||||
|
);
|
||||||
|
|
||||||
|
match cmd {
|
||||||
|
IpcControlCmd::IPC_RMID => {
|
||||||
|
let mut sem_sets_mut = sem_sets_mut();
|
||||||
|
let sem_set = sem_sets_mut.get(&semid).ok_or(Error::new(Errno::EINVAL))?;
|
||||||
|
|
||||||
|
let euid = ctx.posix_thread.credentials().euid();
|
||||||
|
let permission = sem_set.permission();
|
||||||
|
let can_removed = (euid == permission.uid()) || (euid == permission.cuid());
|
||||||
|
if !can_removed {
|
||||||
|
return_errno!(Errno::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
sem_sets_mut
|
||||||
|
.remove(&semid)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?;
|
||||||
|
}
|
||||||
|
IpcControlCmd::SEM_SETVAL => {
|
||||||
|
// In setval, arg is parse as i32
|
||||||
|
let val = arg as i32;
|
||||||
|
if val < 0 {
|
||||||
|
return_errno!(Errno::ERANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_and_ctl(semid, PermissionMode::ALTER, |sem_set| {
|
||||||
|
let sem = sem_set
|
||||||
|
.get(semnum as usize)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?;
|
||||||
|
|
||||||
|
sem.set_val(val)?;
|
||||||
|
sem_set.update_ctime();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
IpcControlCmd::SEM_GETVAL => {
|
||||||
|
let val: i32 = check_and_ctl(semid, PermissionMode::READ, |sem_set| {
|
||||||
|
Ok(sem_set
|
||||||
|
.get(semnum as usize)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?
|
||||||
|
.val())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(SyscallReturn::Return(val as isize));
|
||||||
|
}
|
||||||
|
IpcControlCmd::SEM_GETPID => {
|
||||||
|
let pid: Pid = check_and_ctl(semid, PermissionMode::READ, |sem_set| {
|
||||||
|
Ok(sem_set
|
||||||
|
.get(semnum as usize)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?
|
||||||
|
.last_modified_pid())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(SyscallReturn::Return(pid as isize));
|
||||||
|
}
|
||||||
|
IpcControlCmd::SEM_GETZCNT => {
|
||||||
|
let cnt: usize = check_and_ctl(semid, PermissionMode::READ, |sem_set| {
|
||||||
|
Ok(sem_set
|
||||||
|
.get(semnum as usize)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?
|
||||||
|
.pending_zero_count())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(SyscallReturn::Return(cnt as isize));
|
||||||
|
}
|
||||||
|
IpcControlCmd::SEM_GETNCNT => {
|
||||||
|
let cnt: usize = check_and_ctl(semid, PermissionMode::READ, |sem_set| {
|
||||||
|
Ok(sem_set
|
||||||
|
.get(semnum as usize)
|
||||||
|
.ok_or(Error::new(Errno::EINVAL))?
|
||||||
|
.pending_alter_count())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(SyscallReturn::Return(cnt as isize));
|
||||||
|
}
|
||||||
|
_ => todo!("Need to support {:?} in SYS_SEMCTL", cmd),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_and_ctl<T, F>(semid: i32, permission: PermissionMode, ctl_func: F) -> Result<T>
|
||||||
|
where
|
||||||
|
F: FnOnce(&SemaphoreSet) -> Result<T>,
|
||||||
|
{
|
||||||
|
check_sem(semid, None, permission)?;
|
||||||
|
let sem_sets = sem_sets();
|
||||||
|
let sem_set = sem_sets.get(&semid).ok_or(Error::new(Errno::EINVAL))?;
|
||||||
|
ctl_func.call_once((sem_set,))
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user