Implement semget syscall

This commit is contained in:
Yuke Peng 2024-08-10 18:50:59 +08:00 committed by Tate, Hongliang Tian
parent b7a5f797de
commit 4530253a99
4 changed files with 70 additions and 1 deletions

View File

@ -84,7 +84,7 @@ provided by Linux on x86-64 architecture.
| 61 | wait4 | ✅ |
| 62 | kill | ✅ |
| 63 | uname | ✅ |
| 64 | semget | |
| 64 | semget | |
| 65 | semop | ❌ |
| 66 | semctl | ❌ |
| 67 | shmdt | ❌ |

View File

@ -89,6 +89,7 @@ use crate::syscall::{
sched_getaffinity::sys_sched_getaffinity,
sched_yield::sys_sched_yield,
select::sys_select,
semget::sys_semget,
sendfile::sys_sendfile,
sendmsg::sys_sendmsg,
sendto::sys_sendto,
@ -190,6 +191,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_WAIT4 = 61 => sys_wait4(args[..4]);
SYS_KILL = 62 => sys_kill(args[..2]);
SYS_UNAME = 63 => sys_uname(args[..1]);
SYS_SEMGET = 64 => sys_semget(args[..3]);
SYS_FCNTL = 72 => sys_fcntl(args[..3]);
SYS_FLOCK = 73 => sys_flock(args[..2]);
SYS_FSYNC = 74 => sys_fsync(args[..1]);

View File

@ -96,6 +96,7 @@ mod rt_sigsuspend;
mod sched_getaffinity;
mod sched_yield;
mod select;
mod semget;
mod sendfile;
mod sendmsg;
mod sendto;

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::{
ipc::{
semaphore::system_v::{
sem_set::{check_sem, create_sem_set, create_sem_set_with_id, SEMMSL},
PermissionMode,
},
IpcFlags,
},
prelude::*,
};
pub fn sys_semget(key: i32, nsems: i32, semflags: i32, ctx: &Context) -> Result<SyscallReturn> {
if nsems < 0 || nsems as usize > SEMMSL {
return_errno!(Errno::EINVAL);
}
let flags = IpcFlags::from_bits_truncate(semflags as u32);
let mode: u16 = (semflags as u32 & 0x1FF) as u16;
let nsems = nsems as usize;
let credentials = ctx.posix_thread.credentials();
debug!(
"[sys_semget] key = {}, nsems = {}, flags = {:?}",
key, nsems, semflags
);
// Create a new semaphore set directly
const IPC_NEW: i32 = 0;
if key == IPC_NEW {
if nsems == 0 {
return_errno!(Errno::EINVAL);
}
return Ok(SyscallReturn::Return(
create_sem_set(nsems, mode, credentials)? as isize,
));
}
// Get a semaphore set, and create if necessary
match check_sem(
key,
Some(nsems),
PermissionMode::ALTER | PermissionMode::READ,
) {
Ok(_) => {
if flags.contains(IpcFlags::IPC_CREAT | IpcFlags::IPC_EXCL) {
return_errno!(Errno::EEXIST);
}
}
Err(err) => {
let need_create = err.error() == Errno::ENOENT && flags.contains(IpcFlags::IPC_CREAT);
if !need_create {
return Err(err);
}
if nsems == 0 {
return_errno!(Errno::EINVAL);
}
create_sem_set_with_id(key, nsems, mode, credentials)?
}
};
Ok(SyscallReturn::Return(key as isize))
}