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:
parent
a99f4396eb
commit
b7a192a1ea
@ -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)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user