1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 16:16:16 +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::Semaphore;
use crate::sync::SpinLock as Mutex; 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 alloc::{collections::BTreeMap, sync::Arc, sync::Weak, vec::Vec};
use bitflags::*;
use core::ops::Index; use core::ops::Index;
use spin::RwLock; 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 // structure specifies the access permissions on the semaphore set
// key_t? // key_t?
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -19,6 +28,7 @@ pub struct IpcPerm {
} }
// semid data structure // semid data structure
// struct semid_ds
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct SemidDs { pub struct SemidDs {
pub perm: IpcPerm, /* Ownership and permissions */ pub perm: IpcPerm, /* Ownership and permissions */
@ -60,22 +70,48 @@ impl SemArray {
self.semid_ds.lock().ctime = TimeSpec::get_epoch().sec; 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`. /// Get the semaphore array with `key`.
/// If not exist, create a new one with `nsems` elements. /// 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 mut key2sem = KEY2SEM.write();
let flag = SemGetFlag::from_bits_truncate(flags);
// found in the map 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(weak_array) = key2sem.get(&key) {
if let Some(array) = weak_array.upgrade() { if let Some(array) = weak_array.upgrade() {
return array; if flag.contains(SemGetFlag::CREAT) && flag.contains(SemGetFlag::EXCLUSIVE) {
// exclusive
return Err(SysError::EEXIST);
}
return Ok(array);
} }
} }
}
// not found, create one // not found, create one
let mut semaphores = Vec::new(); let mut semaphores = Vec::new();
for _ in 0..nsems { for _ in 0..nsems {
semaphores.push(Semaphore::new(0)); semaphores.push(Semaphore::new(0));
} }
// insert to global map // insert to global map
let array = Arc::new(SemArray { let array = Arc::new(SemArray {
semid_ds: Mutex::new(SemidDs { semid_ds: Mutex::new(SemidDs {
@ -85,6 +121,7 @@ impl SemArray {
gid: 0, gid: 0,
cuid: 0, cuid: 0,
cgid: 0, cgid: 0,
// least significant 9 bits
mode: (flags as u16) & 0x1ff, mode: (flags as u16) & 0x1ff,
__seq: 0, __seq: 0,
}, },
@ -95,6 +132,6 @@ impl SemArray {
sems: semaphores, sems: semaphores,
}); });
key2sem.insert(key, Arc::downgrade(&array)); key2sem.insert(key, Arc::downgrade(&array));
array Ok(array)
} }
} }

View File

@ -12,18 +12,17 @@ use rcore_memory::{PhysAddr, VirtAddr, PAGE_SIZE};
use super::*; use super::*;
impl Syscall<'_> { impl Syscall<'_> {
pub fn sys_semget(&self, key: usize, nsems: isize, flags: usize) -> SysResult { pub fn sys_semget(&self, key: usize, nsems: usize, flags: usize) -> SysResult {
info!("semget: key: {}", key); info!("semget: key: {} nsems: {} flags: {:#x}", key, nsems, flags);
/// The maximum semaphores per semaphore set /// The maximum semaphores per semaphore set
const SEMMSL: usize = 256; const SEMMSL: usize = 256;
if nsems < 0 || nsems as usize > SEMMSL { if nsems > SEMMSL {
return Err(SysError::EINVAL); 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); let id = self.process().semaphores.add(sem_array);
Ok(id) Ok(id)
} }
@ -54,8 +53,11 @@ impl Syscall<'_> {
Ok(0) Ok(0)
} }
pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: isize) -> SysResult { pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: usize) -> SysResult {
info!("semctl: id: {}, num: {}, cmd: {}", id, num, cmd); info!(
"semctl: id: {}, num: {}, cmd: {} arg: {:#x}",
id, num, cmd, arg
);
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?; let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
const IPC_RMID: usize = 0; const IPC_RMID: usize = 0;
const IPC_SET: usize = 1; const IPC_SET: usize = 1;
@ -70,11 +72,16 @@ impl Syscall<'_> {
match cmd { match cmd {
IPC_RMID => { IPC_RMID => {
// arg is struct semid_ds
sem_array.remove(); sem_array.remove();
Ok(0) Ok(0)
} }
IPC_SET => { 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(); sem_array.ctime();
Ok(0) Ok(0)
} }
@ -91,7 +98,7 @@ impl Syscall<'_> {
GETNCNT => Ok(sem.get_ncnt()), GETNCNT => Ok(sem.get_ncnt()),
GETZCNT => Ok(0), GETZCNT => Ok(0),
SETVAL => { SETVAL => {
sem.set(arg); sem.set(arg as isize);
sem.set_pid(self.process().pid.get()); sem.set_pid(self.process().pid.get());
sem_array.ctime(); sem_array.ctime();
Ok(0) Ok(0)

View File

@ -347,11 +347,11 @@ impl Syscall<'_> {
// sem // sem
#[cfg(not(target_arch = "mips"))] #[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"))] #[cfg(not(target_arch = "mips"))]
SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]),
#[cfg(not(target_arch = "mips"))] #[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)), SYS_MSGGET => self.unimplemented("msgget", Ok(0)),
#[cfg(target_arch = "mips")] #[cfg(target_arch = "mips")]
SYS_SHMGET => self.unimplemented("shmget", Ok(0)), SYS_SHMGET => self.unimplemented("shmget", Ok(0)),
@ -439,7 +439,6 @@ impl Syscall<'_> {
} else { } else {
error!("unknown syscall id: {}, args: {:x?}", id, args); error!("unknown syscall id: {}, args: {:x?}", id, args);
todo!() todo!()
//crate::trap::error(self.tf);
} }
} }
}; };
@ -511,7 +510,7 @@ impl Syscall<'_> {
SYS_IPC => match args[0] { SYS_IPC => match args[0] {
1 => self.sys_semop(args[1], args[2] as *const SemBuf, args[3]), 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]), 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, _ => return None,
}, },
SYS_EPOLL_CREATE => self.sys_epoll_create(args[0]), SYS_EPOLL_CREATE => self.sys_epoll_create(args[0]),