1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 16:16:16 +04:00

move all process related semaphore operations to struct SemProc

This commit is contained in:
Runji Wang 2019-10-24 20:33:00 +08:00
parent a99f4396eb
commit b7a192a1ea
3 changed files with 83 additions and 38 deletions

View File

@ -1,3 +1,72 @@
mod semary;
pub use self::semary::*;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
/// Semaphore table in a process
#[derive(Default)]
pub struct SemProc {
/// Semaphore arrays
arrays: BTreeMap<SemId, Arc<SemArray>>,
/// Undo operations when process terminates
undos: BTreeMap<(SemId, SemNum), SemOp>,
}
/// Semaphore set identifier (in a process)
type SemId = usize;
/// Semaphore number (in an array)
type SemNum = u16;
/// Semaphore operation value
type SemOp = i16;
impl SemProc {
/// Insert the `array` and return its ID
pub fn add(&mut self, array: Arc<SemArray>) -> SemId {
let id = self.get_free_id();
self.arrays.insert(id, array);
id
}
/// Get a free ID
fn get_free_id(&self) -> SemId {
(0..).find(|i| self.arrays.get(i).is_none()).unwrap()
}
/// Get an semaphore set by `id`
pub fn get(&self, id: SemId) -> Option<Arc<SemArray>> {
self.arrays.get(&id).map(|a| a.clone())
}
/// Add an undo operation
pub fn add_undo(&mut self, id: SemId, num: SemNum, op: SemOp) {
let old_val = *self.undos.get(&(id, num)).unwrap_or(&0);
let new_val = old_val - op;
self.undos.insert((id, num), new_val);
}
}
/// Fork the semaphore table. Clear undo info.
impl Clone for SemProc {
fn clone(&self) -> Self {
SemProc {
arrays: self.arrays.clone(),
undos: BTreeMap::default(),
}
}
}
/// Auto perform semaphores undo on drop
impl Drop for SemProc {
fn drop(&mut self) {
for (&(id, num), &op) in self.undos.iter() {
debug!("semundo: id: {}, num: {}, op: {}", id, num, op);
let sem_array = self.arrays[&id].clone();
let sem = &sem_array[num as usize];
match op {
1 => sem.release(),
0 => {}
_ => unimplemented!("Semaphore: semundo.(Not 1)"),
}
}
}
}

View File

@ -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::SemArray;
use crate::ipc::SemProc;
use crate::memory::{
ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read,
};
@ -65,8 +65,7 @@ pub struct Process {
pub cwd: String,
pub exec_path: String,
futexes: BTreeMap<usize, Arc<Condvar>>,
pub semaphores: BTreeMap<usize, Arc<SemArray>>,
pub semundos: BTreeMap<(usize, i16), i16>,
pub semaphores: SemProc,
// relationship
pub pid: Pid, // i.e. tgid, usually the tid of first thread
@ -127,8 +126,7 @@ impl Thread {
files: BTreeMap::default(),
cwd: String::from("/"),
exec_path: String::new(),
semaphores: BTreeMap::default(),
semundos: BTreeMap::default(),
semaphores: SemProc::default(),
futexes: BTreeMap::default(),
pid: Pid(0),
parent: Weak::new(),
@ -313,8 +311,7 @@ impl Thread {
cwd: String::from("/"),
exec_path: String::from(exec_path),
futexes: BTreeMap::default(),
semaphores: BTreeMap::default(),
semundos: BTreeMap::default(),
semaphores: SemProc::default(),
pid: Pid(0),
parent: Weak::new(),
children: Vec::new(),
@ -342,7 +339,6 @@ impl Thread {
exec_path: proc.exec_path.clone(),
futexes: BTreeMap::default(),
semaphores: proc.semaphores.clone(),
semundos: BTreeMap::default(),
pid: Pid(0),
parent: Arc::downgrade(&self.proc),
children: Vec::new(),
@ -419,25 +415,9 @@ impl Process {
self.futexes.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
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)"),
}
}
// quit all threads
for tid in self.threads.iter() {
processor().manager().exit(*tid, 1);

View File

@ -21,12 +21,8 @@ impl Syscall<'_> {
}
let nsems = nsems as usize;
let mut proc = self.process();
let mut semarray_table = &mut proc.semaphores;
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);
let sem_array = SemArray::get_or_create(key, nsems, flags);
let id = self.process().semaphores.add(sem_array);
Ok(id)
}
@ -34,7 +30,7 @@ impl Syscall<'_> {
info!("semop: id: {}", id);
let ops = unsafe { self.vm().check_read_array(ops, num_ops)? };
let sem_array = self.process().get_semarray(id);
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
for &SemBuf { num, op, flags } in ops.iter() {
let flags = SemFlags::from_bits_truncate(flags);
if flags.contains(SemFlags::IPC_NOWAIT) {
@ -48,10 +44,7 @@ impl Syscall<'_> {
_ => unimplemented!("Semaphore: semop.(Not 1/-1)"),
};
if flags.contains(SemFlags::SEM_UNDO) {
let mut proc = self.process();
let old_val = *proc.semundos.get(&(id, num)).unwrap_or(&0);
let new_val = old_val - op;
proc.semundos.insert((id, num), new_val);
self.process().semaphores.add_undo(id, num, op);
}
}
Ok(0)
@ -59,8 +52,7 @@ impl Syscall<'_> {
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(id);
let sem_array = self.process().semaphores.get(id).ok_or(SysError::EINVAL)?;
let sem = &sem_array[num as usize];
const GETVAL: usize = 12;
@ -76,9 +68,12 @@ impl Syscall<'_> {
}
}
/// An operation to be performed on a single semaphore
///
/// Ref: [http://man7.org/linux/man-pages/man2/semop.2.html]
#[repr(C)]
pub struct SemBuf {
num: i16,
num: u16,
op: i16,
flags: i16,
}
@ -93,6 +88,7 @@ bitflags! {
pub struct SemFlags: i16 {
/// For SemOP
const IPC_NOWAIT = 0x800;
/// it will be automatically undone when the process terminates.
const SEM_UNDO = 0x1000;
}
}