1
0
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:
Jiajie Chen 2020-06-30 14:08:25 +08:00
parent 6a0e25431b
commit 7b9c85840e
3 changed files with 63 additions and 20 deletions

View File

@ -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)
}
}

View File

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

View File

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