mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
clean and improve code
This commit is contained in:
parent
0b05a58e3b
commit
a99f4396eb
@ -1 +0,0 @@
|
||||
make run arch=x86_64
|
@ -1,3 +1,3 @@
|
||||
pub mod semary;
|
||||
mod semary;
|
||||
|
||||
pub use self::semary::*;
|
||||
|
@ -1,77 +1,49 @@
|
||||
use crate::sync::Semaphore;
|
||||
use crate::sync::SpinLock as Mutex;
|
||||
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec};
|
||||
use core::cell::UnsafeCell;
|
||||
use lazy_static::lazy_static;
|
||||
use core::ops::Index;
|
||||
use spin::RwLock;
|
||||
|
||||
pub trait SemArrTrait {
|
||||
fn get_x(&self, x: usize) -> &Semaphore;
|
||||
}
|
||||
|
||||
/// A System V semaphore set
|
||||
pub struct SemArray {
|
||||
pub key: usize,
|
||||
pub sems: Vec<Semaphore>,
|
||||
key: usize,
|
||||
sems: Vec<Semaphore>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for SemArray {}
|
||||
unsafe impl Send for SemArray {}
|
||||
|
||||
impl SemArray {
|
||||
pub fn new(key: usize, sems: Vec<Semaphore>) -> SemArray {
|
||||
SemArray {
|
||||
key: key,
|
||||
sems: sems,
|
||||
}
|
||||
impl Index<usize> for SemArray {
|
||||
type Output = Semaphore;
|
||||
fn index(&self, idx: usize) -> &Semaphore {
|
||||
&self.sems[idx]
|
||||
}
|
||||
}
|
||||
|
||||
impl SemArrTrait for SemArray {
|
||||
fn get_x(&self, x: usize) -> &Semaphore {
|
||||
&self.sems[x]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SemBuf {
|
||||
pub sem_num: i16,
|
||||
pub sem_op: i16,
|
||||
pub sem_flg: i16,
|
||||
}
|
||||
|
||||
pub struct SemUndo {
|
||||
pub sem_id: i16,
|
||||
pub sem_num: i16,
|
||||
pub sem_op: i16,
|
||||
}
|
||||
|
||||
pub union SemctlUnion {
|
||||
pub val: isize,
|
||||
pub buf: usize, // semid_ds*, unimplemented
|
||||
pub array: usize, // short*, unimplemented
|
||||
} // unused
|
||||
|
||||
lazy_static! {
|
||||
pub static ref KEY2SEM: RwLock<BTreeMap<usize, Weak<SemArray>>> =
|
||||
RwLock::new(BTreeMap::new()); // not mentioned.
|
||||
static ref KEY2SEM: RwLock<BTreeMap<usize, Weak<SemArray>>> = RwLock::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc<SemArray> {
|
||||
let mut key2sem_table = KEY2SEM.write();
|
||||
let mut sem_array_ref: Arc<SemArray>;
|
||||
impl SemArray {
|
||||
/// 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> {
|
||||
let mut key2sem = KEY2SEM.write();
|
||||
|
||||
let mut key_sem_array_ref = key2sem_table.get(&key);
|
||||
if (key_sem_array_ref.is_none() || key_sem_array_ref.unwrap().upgrade().is_none()) {
|
||||
let mut semaphores: Vec<Semaphore> = Vec::new();
|
||||
// found in the map
|
||||
if let Some(weak_array) = key2sem.get(&key) {
|
||||
if let Some(array) = weak_array.upgrade() {
|
||||
return array;
|
||||
}
|
||||
}
|
||||
// not found, create one
|
||||
let mut semaphores = Vec::new();
|
||||
for i in 0..nsems {
|
||||
semaphores.push(Semaphore::new(0));
|
||||
}
|
||||
|
||||
let mut sem_array = SemArray::new(key, semaphores);
|
||||
sem_array_ref = Arc::new(sem_array);
|
||||
key2sem_table.insert(key, Arc::downgrade(&sem_array_ref));
|
||||
} else {
|
||||
sem_array_ref = key2sem_table.get(&key).unwrap().upgrade().unwrap(); // no security check
|
||||
// insert to global map
|
||||
let array = Arc::new(SemArray {
|
||||
key,
|
||||
sems: semaphores,
|
||||
});
|
||||
key2sem.insert(key, Arc::downgrade(&array));
|
||||
array
|
||||
}
|
||||
|
||||
sem_array_ref
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use xmas_elf::{
|
||||
|
||||
use crate::arch::interrupt::{Context, TrapFrame};
|
||||
use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH};
|
||||
use crate::ipc::{SemArrTrait, SemArray, SemUndo};
|
||||
use crate::ipc::SemArray;
|
||||
use crate::memory::{
|
||||
ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read,
|
||||
};
|
||||
@ -419,23 +419,19 @@ impl Process {
|
||||
self.futexes.get(&uaddr).unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn get_semarray(&mut self, uaddr: usize) -> Arc<SemArray> {
|
||||
self.semaphores.get(&uaddr).unwrap().clone()
|
||||
pub fn get_semarray(&mut self, id: usize) -> Arc<SemArray> {
|
||||
self.semaphores.get(&id).unwrap().clone()
|
||||
}
|
||||
|
||||
/// Exit the process.
|
||||
/// Kill all threads and notify parent with the exit code.
|
||||
pub fn exit(&mut self, exit_code: usize) {
|
||||
// perform semaphores undo
|
||||
let sem_undos = self.semundos.clone();
|
||||
for ((sem_id, sem_num), sem_op) in sem_undos.iter() {
|
||||
info!(
|
||||
"sem_arr: {}, sem_num: {}, sem_op: {}",
|
||||
*sem_id, *sem_num, *sem_op
|
||||
);
|
||||
let sem_array = self.get_semarray(*sem_id);
|
||||
let sem_ptr = sem_array.get_x(*sem_num as usize);
|
||||
match (*sem_op) {
|
||||
for (&(id, num), &op) in self.semundos.iter() {
|
||||
debug!("semundo: id: {}, num: {}, op: {}", id, num, op);
|
||||
let sem_array = self.semaphores[&id].clone();
|
||||
let sem_ptr = &sem_array[num as usize];
|
||||
match op {
|
||||
1 => sem_ptr.release(),
|
||||
0 => {}
|
||||
_ => unimplemented!("Semaphore: semundo.(Not 1)"),
|
||||
|
@ -41,9 +41,6 @@ impl Semaphore {
|
||||
count = self.cvar.wait(count);
|
||||
}
|
||||
*count -= 1;
|
||||
/*if (*count > 0) {
|
||||
self.cvar.notify_one();
|
||||
}*/
|
||||
}
|
||||
|
||||
/// Release a resource from this semaphore.
|
||||
@ -65,48 +62,38 @@ impl Semaphore {
|
||||
SemaphoreGuard { sem: self }
|
||||
}
|
||||
|
||||
pub fn check(&self, k: isize) -> Result<bool, ()> {
|
||||
/// Get the current count
|
||||
pub fn get(&self) -> isize {
|
||||
let mut count = self.lock.lock();
|
||||
Ok((*count) >= k)
|
||||
*count
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Result<isize, ()> {
|
||||
/// Set the current count
|
||||
pub fn set(&self, value: isize) {
|
||||
let mut count = self.lock.lock();
|
||||
Ok((*count))
|
||||
}
|
||||
|
||||
pub fn set(&self, k: isize) -> Result<(), ()> {
|
||||
let mut count = self.lock.lock();
|
||||
*count = k;
|
||||
Ok(())
|
||||
*count = value;
|
||||
}
|
||||
|
||||
/// Modify by k atomically. when wait is false avoid waiting. unused
|
||||
pub fn modify(&self, k: isize, wait: bool) -> Result<usize, ()> {
|
||||
match (k) {
|
||||
k if k > 0 => {
|
||||
*(self.lock.lock()) += k;
|
||||
if k > 0 {
|
||||
*(self.lock.lock()) += k;
|
||||
self.cvar.notify_one();
|
||||
} else if k <= 0 {
|
||||
let mut count = self.lock.lock();
|
||||
let mut temp_k = k;
|
||||
while *count + temp_k < 0 {
|
||||
if wait == false {
|
||||
return Err(());
|
||||
}
|
||||
temp_k += *count;
|
||||
*count = 0;
|
||||
count = self.cvar.wait(count);
|
||||
}
|
||||
*count += temp_k;
|
||||
if *count > 0 {
|
||||
self.cvar.notify_one();
|
||||
}
|
||||
k if k <= 0 => {
|
||||
let mut count = self.lock.lock();
|
||||
let mut temp_k = k;
|
||||
while (*count + temp_k < 0) {
|
||||
if wait == false {
|
||||
return Err(());
|
||||
}
|
||||
temp_k += *count;
|
||||
*count = 0;
|
||||
count = self.cvar.wait(count);
|
||||
}
|
||||
*count += temp_k;
|
||||
if (*count > 0) {
|
||||
self.cvar.notify_one();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(()); //unknown error?
|
||||
}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -5,114 +5,94 @@ use bitflags::*;
|
||||
use core::cell::UnsafeCell;
|
||||
use spin::RwLock;
|
||||
|
||||
pub use crate::ipc::new_semary;
|
||||
pub use crate::ipc::semary::SemArrTrait;
|
||||
pub use crate::ipc::SemArray;
|
||||
pub use crate::ipc::SemBuf;
|
||||
pub use crate::ipc::SemctlUnion;
|
||||
pub use crate::ipc::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_semget(&self, key: usize, nsems: usize, semflg: usize) -> SysResult {
|
||||
info!("sys_semget: key: {}", key);
|
||||
let SEMMSL: usize = 256;
|
||||
if (nsems < 0 || nsems > SEMMSL) {
|
||||
pub fn sys_semget(&self, key: usize, nsems: isize, flags: usize) -> SysResult {
|
||||
info!("semget: key: {}", key);
|
||||
|
||||
/// The maximum semaphores per semaphore set
|
||||
const SEMMSL: usize = 256;
|
||||
|
||||
if nsems < 0 || nsems as usize > SEMMSL {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
let nsems = nsems as usize;
|
||||
|
||||
let mut proc = self.process();
|
||||
let mut semarray_table = &mut proc.semaphores;
|
||||
|
||||
let sem_id = (0..)
|
||||
.find(|i| match semarray_table.get(i) {
|
||||
Some(p) => false,
|
||||
_ => true,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut sem_array: Arc<SemArray> = new_semary(key, nsems, semflg);
|
||||
|
||||
semarray_table.insert(sem_id, sem_array);
|
||||
Ok(sem_id)
|
||||
let id = (0..).find(|i| semarray_table.get(i).is_none()).unwrap();
|
||||
let mut sem_array = SemArray::get_or_create(key, nsems, flags);
|
||||
semarray_table.insert(id, sem_array);
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub fn sys_semop(
|
||||
&self,
|
||||
sem_id: usize,
|
||||
sem_ops: *const SemBuf,
|
||||
num_sem_ops: usize,
|
||||
) -> SysResult {
|
||||
info!("sys_semop: sem_id: {}", sem_id);
|
||||
let sem_ops = unsafe { self.vm().check_read_array(sem_ops, num_sem_ops)? };
|
||||
pub fn sys_semop(&self, id: usize, ops: *const SemBuf, num_ops: usize) -> SysResult {
|
||||
info!("semop: id: {}", id);
|
||||
let ops = unsafe { self.vm().check_read_array(ops, num_ops)? };
|
||||
|
||||
for sembuf in sem_ops.iter() {
|
||||
if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) {
|
||||
let sem_array = self.process().get_semarray(id);
|
||||
for &SemBuf { num, op, flags } in ops.iter() {
|
||||
let flags = SemFlags::from_bits_truncate(flags);
|
||||
if flags.contains(SemFlags::IPC_NOWAIT) {
|
||||
unimplemented!("Semaphore: semop.IPC_NOWAIT");
|
||||
}
|
||||
let sem_array;
|
||||
{
|
||||
let mut proc = self.process();
|
||||
sem_array = proc.get_semarray(sem_id);
|
||||
}
|
||||
let sem_ptr = sem_array.get_x(sembuf.sem_num as usize);
|
||||
let sem = &sem_array[num as usize];
|
||||
|
||||
let mut result;
|
||||
|
||||
match (sembuf.sem_op) {
|
||||
1 => result = sem_ptr.release(),
|
||||
-1 => result = sem_ptr.acquire(),
|
||||
let _result = match op {
|
||||
1 => sem.release(),
|
||||
-1 => sem.acquire(),
|
||||
_ => unimplemented!("Semaphore: semop.(Not 1/-1)"),
|
||||
}
|
||||
if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) {
|
||||
};
|
||||
if flags.contains(SemFlags::SEM_UNDO) {
|
||||
let mut proc = self.process();
|
||||
let get_key = proc.semundos.get(&(sem_id, sembuf.sem_num));
|
||||
let mut val = 0;
|
||||
if (!get_key.is_none()) {
|
||||
val = *get_key.unwrap();
|
||||
}
|
||||
val -= sembuf.sem_op;
|
||||
proc.semundos.insert((sem_id, sembuf.sem_num), val);
|
||||
let old_val = *proc.semundos.get(&(id, num)).unwrap_or(&0);
|
||||
let new_val = old_val - op;
|
||||
proc.semundos.insert((id, num), new_val);
|
||||
}
|
||||
}
|
||||
info!("sem_op: {}", sem_ops[0].sem_op);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_semctl(&self, sem_id: usize, sem_num: usize, cmd: usize, arg: isize) -> SysResult {
|
||||
info!("sys_semctl: sem_id: {}", sem_id);
|
||||
pub fn sys_semctl(&self, id: usize, num: usize, cmd: usize, arg: isize) -> SysResult {
|
||||
info!("semctl: id: {}, num: {}, cmd: {}", id, num, cmd);
|
||||
let mut proc = self.process();
|
||||
let sem_array: Arc<SemArray> = proc.get_semarray(sem_id);
|
||||
let sem_ptr = sem_array.get_x(sem_num as usize);
|
||||
let sem_array: Arc<SemArray> = proc.get_semarray(id);
|
||||
let sem = &sem_array[num as usize];
|
||||
|
||||
if (cmd == SEMCTLCMD::SETVAL.bits()) {
|
||||
match (sem_ptr.set(arg)) {
|
||||
Ok(()) => {
|
||||
return Ok(0);
|
||||
}
|
||||
_ => {
|
||||
return Err(SysError::EUNDEF);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unimplemented!("Semaphore: Semctl.(Not setval)");
|
||||
const GETVAL: usize = 12;
|
||||
const GETALL: usize = 13;
|
||||
const SETVAL: usize = 16;
|
||||
const SETALL: usize = 17;
|
||||
|
||||
match cmd {
|
||||
SETVAL => sem.set(arg),
|
||||
_ => unimplemented!("Semaphore: Semctl.(Not setval)"),
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SemBuf {
|
||||
num: i16,
|
||||
op: i16,
|
||||
flags: i16,
|
||||
}
|
||||
|
||||
pub union SemctlUnion {
|
||||
val: isize,
|
||||
buf: usize, // semid_ds*, unimplemented
|
||||
array: usize, // short*, unimplemented
|
||||
} // unused
|
||||
|
||||
bitflags! {
|
||||
pub struct SEMFLAGS: i16 {
|
||||
pub struct SemFlags: i16 {
|
||||
/// For SemOP
|
||||
const IPC_NOWAIT = 0x800;
|
||||
const SEM_UNDO = 0x1000;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SEMCTLCMD: usize {
|
||||
//const GETVAL = 12;
|
||||
//const GETALL = 13;
|
||||
const SETVAL = 16;
|
||||
//const SETALL = 17;
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ impl Syscall<'_> {
|
||||
SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
|
||||
|
||||
// sem
|
||||
SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]),
|
||||
SYS_SEMGET => self.sys_semget(args[0], args[1] as isize, args[2]),
|
||||
SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]),
|
||||
SYS_SEMCTL => self.sys_semctl(
|
||||
args[0],
|
||||
|
Loading…
Reference in New Issue
Block a user