mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
Implement IPC_SET for sem
This commit is contained in:
parent
6a0e25431b
commit
7b9c85840e
@ -1,10 +1,19 @@
|
||||
use crate::sync::Semaphore;
|
||||
use crate::sync::SpinLock as Mutex;
|
||||
use crate::syscall::{SemBuf, SysResult, TimeSpec};
|
||||
use crate::syscall::{SemBuf, SysError, SysResult, TimeSpec};
|
||||
use alloc::{collections::BTreeMap, sync::Arc, sync::Weak, vec::Vec};
|
||||
use bitflags::*;
|
||||
use core::ops::Index;
|
||||
use spin::RwLock;
|
||||
|
||||
bitflags! {
|
||||
struct SemGetFlag: usize {
|
||||
const CREAT = 1 << 9;
|
||||
const EXCLUSIVE = 1 << 10;
|
||||
const NO_WAIT = 1 << 11;
|
||||
}
|
||||
}
|
||||
|
||||
// structure specifies the access permissions on the semaphore set
|
||||
// key_t?
|
||||
#[derive(Clone, Copy)]
|
||||
@ -19,6 +28,7 @@ pub struct IpcPerm {
|
||||
}
|
||||
|
||||
// semid data structure
|
||||
// struct semid_ds
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SemidDs {
|
||||
pub perm: IpcPerm, /* Ownership and permissions */
|
||||
@ -60,22 +70,48 @@ impl SemArray {
|
||||
self.semid_ds.lock().ctime = TimeSpec::get_epoch().sec;
|
||||
}
|
||||
|
||||
/// for IPC_SET
|
||||
/// see man semctl(2)
|
||||
pub fn set(&self, new: &SemidDs) {
|
||||
let mut lock = self.semid_ds.lock();
|
||||
lock.perm.uid = new.perm.uid;
|
||||
lock.perm.gid = new.perm.gid;
|
||||
lock.perm.mode = new.perm.mode & 0x1ff;
|
||||
}
|
||||
|
||||
/// Get the semaphore array with `key`.
|
||||
/// If not exist, create a new one with `nsems` elements.
|
||||
pub fn get_or_create(key: usize, nsems: usize, flags: usize) -> Arc<Self> {
|
||||
pub fn get_or_create(
|
||||
mut key: usize,
|
||||
nsems: usize,
|
||||
flags: usize,
|
||||
) -> Result<Arc<Self>, SysError> {
|
||||
let mut key2sem = KEY2SEM.write();
|
||||
let flag = SemGetFlag::from_bits_truncate(flags);
|
||||
|
||||
// found in the map
|
||||
if let Some(weak_array) = key2sem.get(&key) {
|
||||
if let Some(array) = weak_array.upgrade() {
|
||||
return array;
|
||||
if key == 0 {
|
||||
// IPC_PRIVATE
|
||||
// find an empty key slot
|
||||
key = (1usize..).find(|i| key2sem.get(i).is_none()).unwrap();
|
||||
} else {
|
||||
// check existence
|
||||
if let Some(weak_array) = key2sem.get(&key) {
|
||||
if let Some(array) = weak_array.upgrade() {
|
||||
if flag.contains(SemGetFlag::CREAT) && flag.contains(SemGetFlag::EXCLUSIVE) {
|
||||
// exclusive
|
||||
return Err(SysError::EEXIST);
|
||||
}
|
||||
return Ok(array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found, create one
|
||||
let mut semaphores = Vec::new();
|
||||
for _ in 0..nsems {
|
||||
semaphores.push(Semaphore::new(0));
|
||||
}
|
||||
|
||||
// insert to global map
|
||||
let array = Arc::new(SemArray {
|
||||
semid_ds: Mutex::new(SemidDs {
|
||||
@ -85,6 +121,7 @@ impl SemArray {
|
||||
gid: 0,
|
||||
cuid: 0,
|
||||
cgid: 0,
|
||||
// least significant 9 bits
|
||||
mode: (flags as u16) & 0x1ff,
|
||||
__seq: 0,
|
||||
},
|
||||
@ -95,6 +132,6 @@ impl SemArray {
|
||||
sems: semaphores,
|
||||
});
|
||||
key2sem.insert(key, Arc::downgrade(&array));
|
||||
array
|
||||
Ok(array)
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,17 @@ use rcore_memory::{PhysAddr, VirtAddr, PAGE_SIZE};
|
||||
use super::*;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_semget(&self, key: usize, nsems: isize, flags: usize) -> SysResult {
|
||||
info!("semget: key: {}", key);
|
||||
pub fn sys_semget(&self, key: usize, nsems: usize, flags: usize) -> SysResult {
|
||||
info!("semget: key: {} nsems: {} flags: {:#x}", key, nsems, flags);
|
||||
|
||||
/// The maximum semaphores per semaphore set
|
||||
const SEMMSL: usize = 256;
|
||||
|
||||
if nsems < 0 || nsems as usize > SEMMSL {
|
||||
if nsems > SEMMSL {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
let nsems = nsems as usize;
|
||||
|
||||
let sem_array = SemArray::get_or_create(key, nsems, flags);
|
||||
let sem_array = SemArray::get_or_create(key, nsems, flags)?;
|
||||
let id = self.process().semaphores.add(sem_array);
|
||||
Ok(id)
|
||||
}
|
||||
@ -54,8 +53,11 @@ impl Syscall<'_> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: isize) -> SysResult {
|
||||
info!("semctl: id: {}, num: {}, cmd: {}", id, num, cmd);
|
||||
pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: usize) -> SysResult {
|
||||
info!(
|
||||
"semctl: id: {}, num: {}, cmd: {} arg: {:#x}",
|
||||
id, num, cmd, arg
|
||||
);
|
||||
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
|
||||
const IPC_RMID: usize = 0;
|
||||
const IPC_SET: usize = 1;
|
||||
@ -70,11 +72,16 @@ impl Syscall<'_> {
|
||||
|
||||
match cmd {
|
||||
IPC_RMID => {
|
||||
// arg is struct semid_ds
|
||||
sem_array.remove();
|
||||
Ok(0)
|
||||
}
|
||||
IPC_SET => {
|
||||
// TODO: update IpcPerm
|
||||
// arg is struct semid_ds
|
||||
let ptr = UserInPtr::from(arg);
|
||||
let ds: SemidDs = ptr.read()?;
|
||||
// update IpcPerm
|
||||
sem_array.set(&ds);
|
||||
sem_array.ctime();
|
||||
Ok(0)
|
||||
}
|
||||
@ -91,7 +98,7 @@ impl Syscall<'_> {
|
||||
GETNCNT => Ok(sem.get_ncnt()),
|
||||
GETZCNT => Ok(0),
|
||||
SETVAL => {
|
||||
sem.set(arg);
|
||||
sem.set(arg as isize);
|
||||
sem.set_pid(self.process().pid.get());
|
||||
sem_array.ctime();
|
||||
Ok(0)
|
||||
|
@ -347,11 +347,11 @@ impl Syscall<'_> {
|
||||
|
||||
// sem
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
SYS_SEMGET => self.sys_semget(args[0], args[1] as isize, args[2]),
|
||||
SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]),
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]),
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3] as isize),
|
||||
SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]),
|
||||
SYS_MSGGET => self.unimplemented("msgget", Ok(0)),
|
||||
#[cfg(target_arch = "mips")]
|
||||
SYS_SHMGET => self.unimplemented("shmget", Ok(0)),
|
||||
@ -439,7 +439,6 @@ impl Syscall<'_> {
|
||||
} else {
|
||||
error!("unknown syscall id: {}, args: {:x?}", id, args);
|
||||
todo!()
|
||||
//crate::trap::error(self.tf);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -511,7 +510,7 @@ impl Syscall<'_> {
|
||||
SYS_IPC => match args[0] {
|
||||
1 => self.sys_semop(args[1], args[2] as *const SemBuf, args[3]),
|
||||
2 => self.sys_semget(args[1], args[2] as isize, args[3]),
|
||||
3 => self.sys_semctl(args[1], args[2], args[3], args[4] as isize),
|
||||
3 => self.sys_semctl(args[1], args[2], args[3], args[4]),
|
||||
_ => return None,
|
||||
},
|
||||
SYS_EPOLL_CREATE => self.sys_epoll_create(args[0]),
|
||||
|
Loading…
Reference in New Issue
Block a user