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:
parent
6a0e25431b
commit
7b9c85840e
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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]),
|
||||||
|
Loading…
Reference in New Issue
Block a user