From 374c34cd34cdcb530a1e20acba4d5400f7462d42 Mon Sep 17 00:00:00 2001 From: HongboKang Date: Mon, 14 Oct 2019 23:30:20 +0800 Subject: [PATCH 01/14] write code for semget and semop. not compiled yet. --- kernel/src/ipc/mod.rs | 3 ++ kernel/src/ipc/semary.rs | 40 ++++++++++++++++++++ kernel/src/process/structs.rs | 3 ++ kernel/src/sync/semaphore.rs | 22 +++++++++++ kernel/src/syscall/ipc.rs | 69 +++++++++++++++++++++++++++++++++++ kernel/src/syscall/mod.rs | 6 +++ 6 files changed, 143 insertions(+) create mode 100644 kernel/src/ipc/mod.rs create mode 100644 kernel/src/ipc/semary.rs create mode 100644 kernel/src/syscall/ipc.rs diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs new file mode 100644 index 00000000..fa83190c --- /dev/null +++ b/kernel/src/ipc/mod.rs @@ -0,0 +1,3 @@ +mod semary; + +pub use self::semary::*; \ No newline at end of file diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs new file mode 100644 index 00000000..7c52eff7 --- /dev/null +++ b/kernel/src/ipc/semary.rs @@ -0,0 +1,40 @@ + +pub struct SemArray { + pub mut key: i32, + pub mut sems: Vec, +} + +pub struct SemBuf { + pub mut sem_num: i16, + pub mut sem_op: i16, + pub mut sem_flg: i16, +} + +pub struct +lazy_static! { + pub static ref KEY2SEM: RwLock>>> = + RwLock::new(BTreeMap::new()); // not mentioned. +} + +fn new_semary(key: i32, nsems: i32, semflg: i32) -> Arc> { + + let mut key2sem_table = KEY2SEM.write(); + let mut sem_array_ref: Arc>; + + if key2sem_table.get(key) == None { + let mut semaphores: Vec = Vec::new(); + for i in 0..nsems { + semaphores.push(Semaphore::new()); + } + + let mut sem_array = SemArray::new(); + sem_array.key = key; + sem_array.sems = semaphores; + sem_array_ref = Arc::new(sem_array); + key2sem_table.insert(key, sem_array_ref); + } else { + sem_array_ref = key2sem_table.get(key).clone(); // no security check + } + + sem_array_ref +} \ No newline at end of file diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 5a918145..25eb8331 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -18,6 +18,7 @@ use crate::memory::{ ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, }; use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; +use crate::ipc::SemArray; use super::abi::{self, ProcInitInfo}; use crate::processor; @@ -64,6 +65,8 @@ pub struct Process { pub cwd: String, pub exec_path: String, futexes: BTreeMap>, + pub semaphores: RwLock>>>, + pub semops: Vec, // relationship pub pid: Pid, // i.e. tgid, usually the tid of first thread diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index 0f6bef70..38d31445 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -41,6 +41,9 @@ impl Semaphore { count = self.cvar.wait(count); } *count -= 1; + if (count > 0) { + self.cvar.notify_one(); + } } /// Release a resource from this semaphore. @@ -61,6 +64,25 @@ impl Semaphore { self.acquire(); SemaphoreGuard { sem: self } } + + /// Modify by k atomically + pub fn modify(&self, k: isize, wait: bool) -> Result { + match(k) { + k if k > 0 { + self.lock.lock() += k; + self.cvar.notify_one(); + }, + k if k <= 0 { + let mut count = self.lock.lock(); + while *count < k { + if wait == false { + return Err(EAGAIN) + } + count = self.cvar.wait(count); + } + } + } + } } impl<'a> Drop for SemaphoreGuard<'a> { diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs new file mode 100644 index 00000000..8a2d0a69 --- /dev/null +++ b/kernel/src/syscall/ipc.rs @@ -0,0 +1,69 @@ +use crate::sync::Mutex; +use crate::sync::Semaphore; +use spin::RwLock; + +pub use crate::ipc::SemArray; +pub use crate::ipc::SemBuf; + +impl Syscall<'_> { + pub fn sys_semget(key: i32, nsems: i32, semflg: i32) -> SysResult { // ipc not supported yet + i32 SEMMSL = 256; + if (nsems < 0 || nsems > SEMMSL) { + return Err(SysError::EINVAL); + } + + let mut semarray_table = self.process.semaphores.write(); + let sem_id = (0..) + .find(|i| match semarray_table.get(i) { + Some(p) => false, + _ => true, + }) + .unwrap(); + + let mut sem_array : Arc> = new_semary(key, nsems, semflg); + + semarray_table.insert(sem_id, sem_array); + OK(sem_id) + } + + pub fn sys_semop(sem_id: i32, sem_opa: *const SemBuf, num_sem_ops: i32) -> SysResult { + let mut sem_bufs:Vec = Vec::new(); + unsafe { + for i in 0..num_sem_ops { + sem_bufs.push(*(sem_opa + i)); + } + } + + let mut semarray_table = self.process.semaphores.write(); + + for sembuf: SemBuf in sem_ops { + let mut wait = true; + if (sembuf.flg == IPC_NOWAIT) { + wait = false; + } + /*match(sembuf.sem_op) { + x if x > 0 => { + let mut semarray: SemArray = semarray_table.get(sem_id).lock(); + semarray.sems[sembuf.sem_num].modify(x, wait); + }, + x if x == 0 => { + + }, + x if x < 0 => { + + } + }*/ + let mut semarray: SemArray = semarray_table.get(sem_id).lock(); + semarray.sems[sembuf.sem_num].modify(x, wait); + } + } + +} + +bitflags! { + pub struct SEMFLAGS: usize { + /// For SemOP + const IPC_NOWAIT = 0x800; + const SEM_UNDO = 0x1000; + } +} \ No newline at end of file diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index bec4ff91..23ccc1d3 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -24,6 +24,7 @@ pub use self::misc::*; pub use self::net::*; pub use self::proc::*; pub use self::time::*; +pub use self::ipc::*; mod custom; mod fs; @@ -259,6 +260,11 @@ 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_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), + SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]), + // system SYS_GETPID => self.sys_getpid(), SYS_GETTID => self.sys_gettid(), From 64cdfa277f8611a8398bac5137c63c5e99319273 Mon Sep 17 00:00:00 2001 From: HongboKang Date: Fri, 18 Oct 2019 02:16:32 +0800 Subject: [PATCH 02/14] pass compilation with semget and part of semop. --- kernel/src/ipc/mod.rs | 2 +- kernel/src/ipc/semary.rs | 43 +++++++++++++++---------- kernel/src/lib.rs | 1 + kernel/src/process/structs.rs | 8 ++++- kernel/src/sync/semaphore.rs | 27 +++++++++++----- kernel/src/syscall/ipc.rs | 59 ++++++++++++++++++----------------- kernel/src/syscall/mod.rs | 3 +- 7 files changed, 88 insertions(+), 55 deletions(-) diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index fa83190c..3d642ba1 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,3 +1,3 @@ -mod semary; +pub mod semary; pub use self::semary::*; \ No newline at end of file diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index 7c52eff7..f5e342d7 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -1,39 +1,50 @@ +use lazy_static::lazy_static; +use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; +use crate::sync::SpinNoIrqLock as Mutex; +use crate::sync::Semaphore; +use spin::RwLock; pub struct SemArray { - pub mut key: i32, - pub mut sems: Vec, + pub key: usize, + pub sems: Vec +} + +impl SemArray { + pub fn new(key: usize, sems: Vec) -> SemArray { + SemArray { + key, + sems + } + } } pub struct SemBuf { - pub mut sem_num: i16, - pub mut sem_op: i16, - pub mut sem_flg: i16, + pub sem_num: i16, + pub sem_op: i16, + pub sem_flg: i16, } -pub struct lazy_static! { - pub static ref KEY2SEM: RwLock>>> = + pub static ref KEY2SEM: RwLock>>> = RwLock::new(BTreeMap::new()); // not mentioned. } -fn new_semary(key: i32, nsems: i32, semflg: i32) -> Arc> { +pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc> { let mut key2sem_table = KEY2SEM.write(); let mut sem_array_ref: Arc>; - if key2sem_table.get(key) == None { + if key2sem_table.get(&key).is_none() { let mut semaphores: Vec = Vec::new(); for i in 0..nsems { - semaphores.push(Semaphore::new()); + semaphores.push(Semaphore::new(0)); } - let mut sem_array = SemArray::new(); - sem_array.key = key; - sem_array.sems = semaphores; - sem_array_ref = Arc::new(sem_array); - key2sem_table.insert(key, sem_array_ref); + let mut sem_array = SemArray::new(key, semaphores); + sem_array_ref = Arc::new(Mutex::new(sem_array)); + key2sem_table.insert(key, Arc::downgrade(&sem_array_ref)); } else { - sem_array_ref = key2sem_table.get(key).clone(); // no security check + sem_array_ref = key2sem_table.get(&key).unwrap().upgrade().unwrap(); // no security check } sem_array_ref diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 9e71ffff..f36d4f10 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -41,6 +41,7 @@ pub mod shell; pub mod sync; pub mod syscall; pub mod trap; +pub mod ipc; #[allow(dead_code)] #[cfg(target_arch = "x86_64")] diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 25eb8331..165fedd5 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -18,7 +18,7 @@ use crate::memory::{ ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, }; use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; -use crate::ipc::SemArray; +use crate::ipc::*; use super::abi::{self, ProcInitInfo}; use crate::processor; @@ -127,6 +127,8 @@ impl Thread { files: BTreeMap::default(), cwd: String::from("/"), exec_path: String::new(), + semaphores: RwLock::new(BTreeMap::new()), + semops: Vec::new(), futexes: BTreeMap::default(), pid: Pid(0), parent: Weak::new(), @@ -311,6 +313,8 @@ impl Thread { cwd: String::from("/"), exec_path: String::from(exec_path), futexes: BTreeMap::default(), + semaphores: RwLock::new(BTreeMap::new()), + semops: Vec::new(), pid: Pid(0), parent: Weak::new(), children: Vec::new(), @@ -337,6 +341,8 @@ impl Thread { cwd: proc.cwd.clone(), exec_path: proc.exec_path.clone(), futexes: BTreeMap::default(), + semaphores: RwLock::new(BTreeMap::new()), + semops: Vec::new(), pid: Pid(0), parent: Arc::downgrade(&self.proc), children: Vec::new(), diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index 38d31445..9ffb0112 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -41,7 +41,7 @@ impl Semaphore { count = self.cvar.wait(count); } *count -= 1; - if (count > 0) { + if (*count > 0) { self.cvar.notify_one(); } } @@ -65,23 +65,34 @@ impl Semaphore { SemaphoreGuard { sem: self } } - /// Modify by k atomically - pub fn modify(&self, k: isize, wait: bool) -> Result { + /// Modify by k atomically. when wait is false avoid waiting. + pub fn modify(&self, k: isize, wait: bool) -> Result { match(k) { - k if k > 0 { - self.lock.lock() += k; + k if k > 0 => { + *(self.lock.lock()) += k; self.cvar.notify_one(); }, - k if k <= 0 { + k if k <= 0 => { let mut count = self.lock.lock(); - while *count < k { + let mut temp_k = k; + while *count < temp_k { if wait == false { - return Err(EAGAIN) + return Err(1) } + temp_k -= *count; + *count = 0; count = self.cvar.wait(count); } + *count -= temp_k; + if (*count > 0) { + self.cvar.notify_one(); + } + } + _ => { + return Err(1); //unknown error? } } + Ok(0) } } diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 8a2d0a69..3161e184 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -1,18 +1,26 @@ -use crate::sync::Mutex; + +use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; +use crate::sync::SpinNoIrqLock as Mutex; use crate::sync::Semaphore; use spin::RwLock; +use bitflags::*; pub use crate::ipc::SemArray; pub use crate::ipc::SemBuf; +pub use crate::ipc::new_semary; +//use crate::ipc::semary::*; + +use super::*; impl Syscall<'_> { - pub fn sys_semget(key: i32, nsems: i32, semflg: i32) -> SysResult { // ipc not supported yet - i32 SEMMSL = 256; + pub fn sys_semget(&self, key: usize, nsems: usize, semflg: usize) -> SysResult { // ipc not supported yet + let SEMMSL: usize = 256; if (nsems < 0 || nsems > SEMMSL) { return Err(SysError::EINVAL); } - let mut semarray_table = self.process.semaphores.write(); + let mut proc = self.process(); + let mut semarray_table = proc.semaphores.write(); let sem_id = (0..) .find(|i| match semarray_table.get(i) { Some(p) => false, @@ -23,45 +31,40 @@ impl Syscall<'_> { let mut sem_array : Arc> = new_semary(key, nsems, semflg); semarray_table.insert(sem_id, sem_array); - OK(sem_id) + Ok(sem_id) } - pub fn sys_semop(sem_id: i32, sem_opa: *const SemBuf, num_sem_ops: i32) -> SysResult { - let mut sem_bufs:Vec = Vec::new(); - unsafe { - for i in 0..num_sem_ops { - sem_bufs.push(*(sem_opa + i)); - } - } + pub fn sys_semop(&self, sem_id: usize, sem_ops: *const SemBuf, num_sem_ops: usize) -> SysResult { + //let mut sem_bufs:Vec = Vec::new(); + let sem_ops = unsafe { self.vm().check_read_array(sem_ops, num_sem_ops)? }; - let mut semarray_table = self.process.semaphores.write(); + let mut proc = self.process(); + let mut semarray_table = proc.semaphores.write(); - for sembuf: SemBuf in sem_ops { + for sembuf in sem_ops.iter() { let mut wait = true; - if (sembuf.flg == IPC_NOWAIT) { + if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) { wait = false; } - /*match(sembuf.sem_op) { - x if x > 0 => { - let mut semarray: SemArray = semarray_table.get(sem_id).lock(); - semarray.sems[sembuf.sem_num].modify(x, wait); + let mut semarray_arc: Arc> = (*semarray_table.get(&sem_id).unwrap()).clone(); + let mut semarray: &SemArray = &*semarray_arc.lock(); + match((*semarray).sems[sembuf.sem_num as usize].modify(sembuf.sem_op as isize, wait)) { + Ok(0) => {}, + Err(1) => { + return Err(SysError::EAGAIN); }, - x if x == 0 => { - - }, - x if x < 0 => { - + _ => { + return Err(SysError::EUNDEF); // unknown error? } - }*/ - let mut semarray: SemArray = semarray_table.get(sem_id).lock(); - semarray.sems[sembuf.sem_num].modify(x, wait); + } } + Ok(0) } } bitflags! { - pub struct SEMFLAGS: usize { + pub struct SEMFLAGS: i16 { /// For SemOP const IPC_NOWAIT = 0x800; const SEM_UNDO = 0x1000; diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 23ccc1d3..80966646 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -34,6 +34,7 @@ mod misc; mod net; mod proc; mod time; +mod ipc; #[cfg(feature = "profile")] use alloc::collections::BTreeMap; @@ -263,7 +264,7 @@ impl Syscall<'_> { // sem SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]), SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), - SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]), + //SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]), // system SYS_GETPID => self.sys_getpid(), From c241ec1f5b5afc20fc505c2f71b558ffd4d7130e Mon Sep 17 00:00:00 2001 From: HongboKang Date: Mon, 21 Oct 2019 14:55:17 +0800 Subject: [PATCH 03/14] finish semget & semop. write a small test on semget. --- kernel/run.sh | 1 + kernel/src/ipc/semary.rs | 13 ++++++++++++- kernel/src/process/structs.rs | 11 ++++++----- kernel/src/sync/semaphore.rs | 5 +++++ kernel/src/syscall/ipc.rs | 16 ++++++++++++---- kernel/src/syscall/mod.rs | 2 +- user | 2 +- 7 files changed, 38 insertions(+), 12 deletions(-) create mode 100755 kernel/run.sh diff --git a/kernel/run.sh b/kernel/run.sh new file mode 100755 index 00000000..911a43e0 --- /dev/null +++ b/kernel/run.sh @@ -0,0 +1 @@ +make run arch=x86_64 diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index f5e342d7..2a11f61b 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -24,13 +24,24 @@ pub struct SemBuf { 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>>> = RwLock::new(BTreeMap::new()); // not mentioned. } pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc> { - let mut key2sem_table = KEY2SEM.write(); let mut sem_array_ref: Arc>; diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 165fedd5..21cd0e1f 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -18,7 +18,8 @@ use crate::memory::{ ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, }; use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; -use crate::ipc::*; +use crate::ipc::SemArray; +use crate::ipc::SemUndo; use super::abi::{self, ProcInitInfo}; use crate::processor; @@ -66,7 +67,7 @@ pub struct Process { pub exec_path: String, futexes: BTreeMap>, pub semaphores: RwLock>>>, - pub semops: Vec, + pub semundos: Vec, // relationship pub pid: Pid, // i.e. tgid, usually the tid of first thread @@ -128,7 +129,7 @@ impl Thread { cwd: String::from("/"), exec_path: String::new(), semaphores: RwLock::new(BTreeMap::new()), - semops: Vec::new(), + semundos: Vec::new(), futexes: BTreeMap::default(), pid: Pid(0), parent: Weak::new(), @@ -314,7 +315,7 @@ impl Thread { exec_path: String::from(exec_path), futexes: BTreeMap::default(), semaphores: RwLock::new(BTreeMap::new()), - semops: Vec::new(), + semundos: Vec::new(), pid: Pid(0), parent: Weak::new(), children: Vec::new(), @@ -342,7 +343,7 @@ impl Thread { exec_path: proc.exec_path.clone(), futexes: BTreeMap::default(), semaphores: RwLock::new(BTreeMap::new()), - semops: Vec::new(), + semundos: Vec::new(), pid: Pid(0), parent: Arc::downgrade(&self.proc), children: Vec::new(), diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index 9ffb0112..9f7f56d7 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -65,6 +65,11 @@ impl Semaphore { SemaphoreGuard { sem: self } } + pub fn check(&self, k: isize) -> Result { + let mut count = self.lock.lock(); + Ok((*count) >= k) + } + /// Modify by k atomically. when wait is false avoid waiting. pub fn modify(&self, k: isize, wait: bool) -> Result { match(k) { diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 3161e184..16be4223 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -8,7 +8,7 @@ use bitflags::*; pub use crate::ipc::SemArray; pub use crate::ipc::SemBuf; pub use crate::ipc::new_semary; -//use crate::ipc::semary::*; +pub use crate::ipc::SemctlUnion; use super::*; @@ -42,13 +42,15 @@ impl Syscall<'_> { let mut semarray_table = proc.semaphores.write(); for sembuf in sem_ops.iter() { - let mut wait = true; if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) { - wait = false; + unimplemented!("Semaphore: semop.IPC_NOWAIT"); + } + if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { + unimplemented!("Semaphore: semop.SEM_UNDO"); } let mut semarray_arc: Arc> = (*semarray_table.get(&sem_id).unwrap()).clone(); let mut semarray: &SemArray = &*semarray_arc.lock(); - match((*semarray).sems[sembuf.sem_num as usize].modify(sembuf.sem_op as isize, wait)) { + match((*semarray).sems[sembuf.sem_num as usize].modify(sembuf.sem_op as isize, true)) { Ok(0) => {}, Err(1) => { return Err(SysError::EAGAIN); @@ -57,10 +59,16 @@ impl Syscall<'_> { return Err(SysError::EUNDEF); // unknown error? } } + /*if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { + proc.semops.push(sembuf); + }*/ } Ok(0) } + pub fn sys_semctl(&self, sem_id: usize, sem_num: usize, cmd: usize, arg: usize) -> SysResult { + unimplemented!("Semaphore: Semctl"); + } } bitflags! { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 80966646..645fb193 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -264,7 +264,7 @@ impl Syscall<'_> { // sem SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]), SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), - //SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]), + SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]/* as SemctlUnion*/), // system SYS_GETPID => self.sys_getpid(), diff --git a/user b/user index 72a9ae02..10ac61f9 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 72a9ae029e90a39a32d14758b20365557ca0bfa5 +Subproject commit 10ac61f9ee5f64f2884b54719203be189ecb189d From d4d57a50954b394021b41103f1eaaa9eca52869b Mon Sep 17 00:00:00 2001 From: LoremKang Date: Mon, 21 Oct 2019 15:33:40 +0800 Subject: [PATCH 04/14] finish semctl.setval. pass compilation. --- kernel/src/sync/semaphore.rs | 19 +++++++++++++++---- kernel/src/syscall/ipc.rs | 31 ++++++++++++++++++++++++++++--- kernel/src/syscall/mod.rs | 2 +- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index 9f7f56d7..adad1eb5 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -65,13 +65,24 @@ impl Semaphore { SemaphoreGuard { sem: self } } - pub fn check(&self, k: isize) -> Result { + pub fn check(&self, k: isize) -> Result { let mut count = self.lock.lock(); Ok((*count) >= k) } + pub fn get(&self) -> Result { + let mut count = self.lock.lock(); + Ok((*count)) + } + + pub fn set(&self, k: isize) -> Result<(), ()> { + let mut count = self.lock.lock(); + *count = k; + Ok(()) + } + /// Modify by k atomically. when wait is false avoid waiting. - pub fn modify(&self, k: isize, wait: bool) -> Result { + pub fn modify(&self, k: isize, wait: bool) -> Result { match(k) { k if k > 0 => { *(self.lock.lock()) += k; @@ -82,7 +93,7 @@ impl Semaphore { let mut temp_k = k; while *count < temp_k { if wait == false { - return Err(1) + return Err(()); } temp_k -= *count; *count = 0; @@ -94,7 +105,7 @@ impl Semaphore { } } _ => { - return Err(1); //unknown error? + return Err(()); //unknown error? } } Ok(0) diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 16be4223..df53c233 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -52,7 +52,7 @@ impl Syscall<'_> { let mut semarray: &SemArray = &*semarray_arc.lock(); match((*semarray).sems[sembuf.sem_num as usize].modify(sembuf.sem_op as isize, true)) { Ok(0) => {}, - Err(1) => { + Err(()) => { return Err(SysError::EAGAIN); }, _ => { @@ -66,8 +66,24 @@ impl Syscall<'_> { Ok(0) } - pub fn sys_semctl(&self, sem_id: usize, sem_num: usize, cmd: usize, arg: usize) -> SysResult { - unimplemented!("Semaphore: Semctl"); + pub fn sys_semctl(&self, sem_id: usize, sem_num: usize, cmd: usize, arg: isize) -> SysResult { + let mut proc = self.process(); + let mut semarray_table = proc.semaphores.write(); + let mut semarray_arc: Arc> = (*semarray_table.get(&sem_id).unwrap()).clone(); + let mut semarray: &SemArray = &*semarray_arc.lock(); + if (cmd == SEMCTLCMD::SETVAL.bits()) { + match (*semarray).sems[sem_num].set(arg) { + Ok(()) => { + return Ok(0); + } + _ => { + return Err(SysError::EUNDEF); + } + } + + } else { + unimplemented!("Semaphore: Semctl.(Not setval)"); + } } } @@ -77,4 +93,13 @@ bitflags! { 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; + } } \ No newline at end of file diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 645fb193..0927de81 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -264,7 +264,7 @@ impl Syscall<'_> { // sem SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]), SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), - SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3]/* as SemctlUnion*/), + SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3] as isize/* as SemctlUnion*/), // system SYS_GETPID => self.sys_getpid(), From 198717c071be1078865741a464cca811e8b0b6fa Mon Sep 17 00:00:00 2001 From: LoremKang Date: Tue, 22 Oct 2019 13:48:17 +0800 Subject: [PATCH 05/14] try to solve the deadlock problem caused by locking SemArray while waiting for Semaphores. --- kernel/src/ipc/semary.rs | 32 +++++++++++++++------ kernel/src/process/structs.rs | 16 +++++++---- kernel/src/sync/semaphore.rs | 12 ++++---- kernel/src/syscall/ipc.rs | 54 +++++++++++++++++++++-------------- 4 files changed, 72 insertions(+), 42 deletions(-) diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index 2a11f61b..df4575a5 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -1,23 +1,39 @@ use lazy_static::lazy_static; use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; -use crate::sync::SpinNoIrqLock as Mutex; +use crate::sync::SpinLock as Mutex; use crate::sync::Semaphore; use spin::RwLock; +use core::cell::UnsafeCell; + +pub unsafe trait SemArrTrait { + //fn new(key: usize, sems: Vec) -> SemArray; + fn get_x(&self, x: usize) -> &Semaphore; +} pub struct SemArray { pub key: usize, - pub sems: Vec + pub sems: UnsafeCell> } +unsafe impl Sync for SemArray {} +unsafe impl Send for SemArray {} + impl SemArray { pub fn new(key: usize, sems: Vec) -> SemArray { SemArray { - key, - sems + key: key, + sems: UnsafeCell::new(sems) } } } +unsafe impl SemArrTrait for SemArray { + fn get_x(&self, x: usize) -> & Semaphore { + //unsafe { &mut self.sems.get()}; + return unsafe {& (*self.sems.get())[x]}; + } +} + pub struct SemBuf { pub sem_num: i16, pub sem_op: i16, @@ -37,13 +53,13 @@ pub union SemctlUnion { } // unused lazy_static! { - pub static ref KEY2SEM: RwLock>>> = + pub static ref KEY2SEM: RwLock>> = RwLock::new(BTreeMap::new()); // not mentioned. } -pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc> { +pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc { let mut key2sem_table = KEY2SEM.write(); - let mut sem_array_ref: Arc>; + let mut sem_array_ref: Arc; if key2sem_table.get(&key).is_none() { let mut semaphores: Vec = Vec::new(); @@ -52,7 +68,7 @@ pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc>, - pub semaphores: RwLock>>>, + pub semaphores: BTreeMap>, pub semundos: Vec, // relationship @@ -128,7 +127,7 @@ impl Thread { files: BTreeMap::default(), cwd: String::from("/"), exec_path: String::new(), - semaphores: RwLock::new(BTreeMap::new()), + semaphores: BTreeMap::default(), semundos: Vec::new(), futexes: BTreeMap::default(), pid: Pid(0), @@ -314,7 +313,7 @@ impl Thread { cwd: String::from("/"), exec_path: String::from(exec_path), futexes: BTreeMap::default(), - semaphores: RwLock::new(BTreeMap::new()), + semaphores: BTreeMap::default(), semundos: Vec::new(), pid: Pid(0), parent: Weak::new(), @@ -342,7 +341,7 @@ impl Thread { cwd: proc.cwd.clone(), exec_path: proc.exec_path.clone(), futexes: BTreeMap::default(), - semaphores: RwLock::new(BTreeMap::new()), + semaphores: proc.semaphores.clone(), semundos: Vec::new(), pid: Pid(0), parent: Arc::downgrade(&self.proc), @@ -419,6 +418,11 @@ impl Process { } self.futexes.get(&uaddr).unwrap().clone() } + + pub fn get_semarray(&mut self, uaddr: usize) -> Arc { + self.semaphores.get(&uaddr).unwrap().clone() + } + /// Exit the process. /// Kill all threads and notify parent with the exit code. pub fn exit(&mut self, exit_code: usize) { diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index adad1eb5..f0055902 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -41,9 +41,9 @@ impl Semaphore { count = self.cvar.wait(count); } *count -= 1; - if (*count > 0) { + /*if (*count > 0) { self.cvar.notify_one(); - } + }*/ } /// Release a resource from this semaphore. @@ -81,7 +81,7 @@ impl Semaphore { Ok(()) } - /// Modify by k atomically. when wait is false avoid waiting. + /// Modify by k atomically. when wait is false avoid waiting. unused pub fn modify(&self, k: isize, wait: bool) -> Result { match(k) { k if k > 0 => { @@ -91,15 +91,15 @@ impl Semaphore { k if k <= 0 => { let mut count = self.lock.lock(); let mut temp_k = k; - while *count < temp_k { + while (*count + temp_k < 0) { if wait == false { return Err(()); } - temp_k -= *count; + temp_k += *count; *count = 0; count = self.cvar.wait(count); } - *count -= temp_k; + *count += temp_k; if (*count > 0) { self.cvar.notify_one(); } diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index df53c233..958b841f 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -1,14 +1,16 @@ use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; -use crate::sync::SpinNoIrqLock as Mutex; +use crate::sync::SpinLock as Mutex; use crate::sync::Semaphore; use spin::RwLock; use bitflags::*; +use core::cell::UnsafeCell; pub use crate::ipc::SemArray; pub use crate::ipc::SemBuf; -pub use crate::ipc::new_semary; -pub use crate::ipc::SemctlUnion; +use crate::ipc::new_semary; +use crate::ipc::SemctlUnion; +use crate::ipc::semary::SemArrTrait; use super::*; @@ -20,7 +22,8 @@ impl Syscall<'_> { } let mut proc = self.process(); - let mut semarray_table = proc.semaphores.write(); + let mut semarray_table/*: &mut BTreeMap>*/ = &mut proc.semaphores; + let sem_id = (0..) .find(|i| match semarray_table.get(i) { Some(p) => false, @@ -28,7 +31,7 @@ impl Syscall<'_> { }) .unwrap(); - let mut sem_array : Arc> = new_semary(key, nsems, semflg); + let mut sem_array : Arc = new_semary(key, nsems, semflg); semarray_table.insert(sem_id, sem_array); Ok(sem_id) @@ -38,8 +41,7 @@ impl Syscall<'_> { //let mut sem_bufs:Vec = Vec::new(); let sem_ops = unsafe { self.vm().check_read_array(sem_ops, num_sem_ops)? }; - let mut proc = self.process(); - let mut semarray_table = proc.semaphores.write(); + //let mut semarray_table/*: &BTreeMap>*/ = proc.semaphores; for sembuf in sem_ops.iter() { if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) { @@ -48,31 +50,39 @@ impl Syscall<'_> { if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { unimplemented!("Semaphore: semop.SEM_UNDO"); } - let mut semarray_arc: Arc> = (*semarray_table.get(&sem_id).unwrap()).clone(); - let mut semarray: &SemArray = &*semarray_arc.lock(); - match((*semarray).sems[sembuf.sem_num as usize].modify(sembuf.sem_op as isize, true)) { - Ok(0) => {}, - Err(()) => { - return Err(SysError::EAGAIN); - }, + //let mut semarray_arc: Arc = (*((*semarray_table).get(&sem_id).unwrap())).clone(); + //let mut semarray: &mut SemArray = &mut *semarray_arc; + let mut proc = self.process(); + let sem_array: Arc = proc.get_semarray(sem_id); + let sem_ptr = sem_array.get_x(sembuf.sem_num as usize); + + let mut result; + match(sembuf.sem_op) { + 1 => { + //result = (*semarray).sems[sembuf.sem_num as usize].release(); + result = sem_ptr.release(); + } + -1 => { + //result = (*semarray).sems[sembuf.sem_num as usize].acquire(); + result = sem_ptr.acquire(); + } _ => { - return Err(SysError::EUNDEF); // unknown error? + unimplemented!("Semaphore: semop.(Not 1/-1)"); } } - /*if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { - proc.semops.push(sembuf); - }*/ } Ok(0) } pub fn sys_semctl(&self, sem_id: usize, sem_num: usize, cmd: usize, arg: isize) -> SysResult { + let mut proc = self.process(); - let mut semarray_table = proc.semaphores.write(); - let mut semarray_arc: Arc> = (*semarray_table.get(&sem_id).unwrap()).clone(); - let mut semarray: &SemArray = &*semarray_arc.lock(); + let sem_array: Arc = proc.get_semarray(sem_id); + let sem_ptr = sem_array.get_x(sem_num as usize); + //let mut sem_ptr: &mut Semaphore = proc.get_semarray(sem_id).get_x(sem_num as usize); + if (cmd == SEMCTLCMD::SETVAL.bits()) { - match (*semarray).sems[sem_num].set(arg) { + match (sem_ptr.set(arg)) { Ok(()) => { return Ok(0); } From a180c3b4bb968e62692e26e8b5422c8e2d792a39 Mon Sep 17 00:00:00 2001 From: LoremKang Date: Tue, 22 Oct 2019 14:30:23 +0800 Subject: [PATCH 06/14] solve the deadlock problem & sometimes pass test. --- kernel/src/ipc/semary.rs | 12 ++++++------ user | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index df4575a5..6770bf8c 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -5,14 +5,14 @@ use crate::sync::Semaphore; use spin::RwLock; use core::cell::UnsafeCell; -pub unsafe trait SemArrTrait { +pub trait SemArrTrait { //fn new(key: usize, sems: Vec) -> SemArray; fn get_x(&self, x: usize) -> &Semaphore; } pub struct SemArray { pub key: usize, - pub sems: UnsafeCell> + pub sems: Vec } unsafe impl Sync for SemArray {} @@ -22,15 +22,15 @@ impl SemArray { pub fn new(key: usize, sems: Vec) -> SemArray { SemArray { key: key, - sems: UnsafeCell::new(sems) + sems: sems } } } -unsafe impl SemArrTrait for SemArray { - fn get_x(&self, x: usize) -> & Semaphore { +impl SemArrTrait for SemArray { + fn get_x(&self, x: usize) -> &Semaphore { //unsafe { &mut self.sems.get()}; - return unsafe {& (*self.sems.get())[x]}; + &self.sems[x] } } diff --git a/user b/user index 10ac61f9..11baf015 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 10ac61f9ee5f64f2884b54719203be189ecb189d +Subproject commit 11baf01577e0ca87ef88e6f1f95d2192e43e5d58 From e6b4c77c05082b3b041dae783b2c7a613352eb11 Mon Sep 17 00:00:00 2001 From: LoremKang Date: Tue, 22 Oct 2019 14:58:48 +0800 Subject: [PATCH 07/14] solve a potential unwrap error. deadlock when child lock first. --- kernel/src/ipc/semary.rs | 3 ++- user | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index 6770bf8c..178b2f61 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -61,7 +61,8 @@ pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc { let mut key2sem_table = KEY2SEM.write(); let mut sem_array_ref: Arc; - if key2sem_table.get(&key).is_none() { + 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 = Vec::new(); for i in 0..nsems { semaphores.push(Semaphore::new(0)); diff --git a/user b/user index 11baf015..746114ac 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 11baf01577e0ca87ef88e6f1f95d2192e43e5d58 +Subproject commit 746114ac65b255ba7bdffba0445a162e767e0a6f From 702ea47ae83b30b1876d04587656690a48051738 Mon Sep 17 00:00:00 2001 From: LoremKang Date: Tue, 22 Oct 2019 16:15:03 +0800 Subject: [PATCH 08/14] fix the deadlock bug. semaphores now work well without SEM_UNDO. --- kernel/src/syscall/ipc.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 958b841f..60b5c76d 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -15,7 +15,8 @@ use crate::ipc::semary::SemArrTrait; use super::*; impl Syscall<'_> { - pub fn sys_semget(&self, key: usize, nsems: usize, semflg: usize) -> SysResult { // ipc not supported yet + 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) { return Err(SysError::EINVAL); @@ -38,6 +39,7 @@ impl Syscall<'_> { } 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 mut sem_bufs:Vec = Vec::new(); let sem_ops = unsafe { self.vm().check_read_array(sem_ops, num_sem_ops)? }; @@ -52,11 +54,16 @@ impl Syscall<'_> { } //let mut semarray_arc: Arc = (*((*semarray_table).get(&sem_id).unwrap())).clone(); //let mut semarray: &mut SemArray = &mut *semarray_arc; - let mut proc = self.process(); - let sem_array: Arc = proc.get_semarray(sem_id); - let sem_ptr = sem_array.get_x(sembuf.sem_num as usize); + + 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 mut result; + match(sembuf.sem_op) { 1 => { //result = (*semarray).sems[sembuf.sem_num as usize].release(); @@ -71,11 +78,12 @@ impl Syscall<'_> { } } } + 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); let mut proc = self.process(); let sem_array: Arc = proc.get_semarray(sem_id); let sem_ptr = sem_array.get_x(sem_num as usize); From 4da6a1471a97e02b65f2c7a0f319d4c17adb3b49 Mon Sep 17 00:00:00 2001 From: LoremKang Date: Tue, 22 Oct 2019 23:23:30 +0800 Subject: [PATCH 09/14] support SEM_UNDO. now support all 3 syscall without safety check. --- kernel/src/process/structs.rs | 21 +++++++++++++++++---- kernel/src/syscall/ipc.rs | 32 ++++++++++++++++---------------- kernel/src/syscall/proc.rs | 1 + user | 2 +- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 1f89937b..cc1ebb55 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -66,7 +66,7 @@ pub struct Process { pub exec_path: String, futexes: BTreeMap>, pub semaphores: BTreeMap>, - pub semundos: Vec, + pub semundos: BTreeMap<(usize, i16), i16>, // relationship pub pid: Pid, // i.e. tgid, usually the tid of first thread @@ -128,7 +128,7 @@ impl Thread { cwd: String::from("/"), exec_path: String::new(), semaphores: BTreeMap::default(), - semundos: Vec::new(), + semundos: BTreeMap::default(), futexes: BTreeMap::default(), pid: Pid(0), parent: Weak::new(), @@ -314,7 +314,7 @@ impl Thread { exec_path: String::from(exec_path), futexes: BTreeMap::default(), semaphores: BTreeMap::default(), - semundos: Vec::new(), + semundos: BTreeMap::default(), pid: Pid(0), parent: Weak::new(), children: Vec::new(), @@ -342,7 +342,7 @@ impl Thread { exec_path: proc.exec_path.clone(), futexes: BTreeMap::default(), semaphores: proc.semaphores.clone(), - semundos: Vec::new(), + semundos: BTreeMap::default(), pid: Pid(0), parent: Arc::downgrade(&self.proc), children: Vec::new(), @@ -426,6 +426,19 @@ impl Process { /// 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) { + 1 => sem_ptr.release(), + 0 => {}, + _ => unimplemented!("Semaphore: semundo.(Not 1)"), + } + } + // quit all threads for tid in self.threads.iter() { processor().manager().exit(*tid, 1); diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 60b5c76d..13464e9a 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -8,9 +8,9 @@ use core::cell::UnsafeCell; pub use crate::ipc::SemArray; pub use crate::ipc::SemBuf; -use crate::ipc::new_semary; -use crate::ipc::SemctlUnion; -use crate::ipc::semary::SemArrTrait; +pub use crate::ipc::new_semary; +pub use crate::ipc::SemctlUnion; +pub use crate::ipc::semary::SemArrTrait; use super::*; @@ -49,9 +49,6 @@ impl Syscall<'_> { if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) { unimplemented!("Semaphore: semop.IPC_NOWAIT"); } - if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { - unimplemented!("Semaphore: semop.SEM_UNDO"); - } //let mut semarray_arc: Arc = (*((*semarray_table).get(&sem_id).unwrap())).clone(); //let mut semarray: &mut SemArray = &mut *semarray_arc; @@ -65,17 +62,20 @@ impl Syscall<'_> { let mut result; match(sembuf.sem_op) { - 1 => { - //result = (*semarray).sems[sembuf.sem_num as usize].release(); - result = sem_ptr.release(); - } - -1 => { - //result = (*semarray).sems[sembuf.sem_num as usize].acquire(); - result = sem_ptr.acquire(); - } - _ => { - unimplemented!("Semaphore: semop.(Not 1/-1)"); + 1 => result = sem_ptr.release(), + -1 => result = sem_ptr.acquire(), + _ => unimplemented!("Semaphore: semop.(Not 1/-1)"), + } + if (sembuf.sem_flg == (SEMFLAGS::SEM_UNDO.bits())) { + 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); + //unimplemented!("Semaphore: semop.SEM_UNDO"); } } info!("sem_op: {}", sem_ops[0].sem_op); diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index fdcfcbea..03f15f40 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -277,6 +277,7 @@ impl Syscall<'_> { queue.notify_one(); } } + drop(proc); processor().manager().exit(tid, exit_code as usize); diff --git a/user b/user index 746114ac..894d98f2 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 746114ac65b255ba7bdffba0445a162e767e0a6f +Subproject commit 894d98f2163c4a96d4bf1990d83ce143ed558bce From 0b05a58e3b272d8f0ec64e66a3716944f01c311e Mon Sep 17 00:00:00 2001 From: LoremKang Date: Thu, 24 Oct 2019 15:50:46 +0800 Subject: [PATCH 10/14] update submodule rboot & user. format the code. --- kernel/src/arch/x86_64/acpi.rs | 3 +-- kernel/src/drivers/gpu/virtio_gpu.rs | 10 +++---- kernel/src/ipc/mod.rs | 2 +- kernel/src/ipc/semary.rs | 22 +++++++--------- kernel/src/lib.rs | 2 +- kernel/src/process/structs.rs | 11 +++++--- kernel/src/sync/semaphore.rs | 6 ++--- kernel/src/syscall/ipc.rs | 39 ++++++++++++---------------- kernel/src/syscall/mod.rs | 11 +++++--- kernel/src/syscall/proc.rs | 2 +- rboot | 2 +- user | 2 +- 12 files changed, 56 insertions(+), 56 deletions(-) diff --git a/kernel/src/arch/x86_64/acpi.rs b/kernel/src/arch/x86_64/acpi.rs index 47973685..dd10a3e6 100644 --- a/kernel/src/arch/x86_64/acpi.rs +++ b/kernel/src/arch/x86_64/acpi.rs @@ -12,8 +12,7 @@ impl AcpiHandler for Handler { ) -> PhysicalMapping { PhysicalMapping { physical_start: physical_address, - virtual_start: NonNull::new(phys_to_virt(physical_address) as *mut T) - .unwrap(), + virtual_start: NonNull::new(phys_to_virt(physical_address) as *mut T).unwrap(), region_length: size, mapped_length: size, } diff --git a/kernel/src/drivers/gpu/virtio_gpu.rs b/kernel/src/drivers/gpu/virtio_gpu.rs index 4f7af881..62589d99 100644 --- a/kernel/src/drivers/gpu/virtio_gpu.rs +++ b/kernel/src/drivers/gpu/virtio_gpu.rs @@ -267,11 +267,11 @@ fn setup_framebuffer(driver: &mut VirtIOGpu) { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(size as usize, PAGE_SIZE).unwrap()) } as usize; // test framebuffer -// mandelbrot( -// driver.rect.width, -// driver.rect.height, -// frame_buffer as *mut u32, -// ); + // mandelbrot( + // driver.rect.width, + // driver.rect.height, + // frame_buffer as *mut u32, + // ); driver.frame_buffer = frame_buffer; let request_resource_attach_backing = unsafe { &mut *(driver.queue_buffer[VIRTIO_BUFFER_TRANSMIT] as *mut VirtIOGpuResourceAttachBacking) diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 3d642ba1..dced3002 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,3 +1,3 @@ pub mod semary; -pub use self::semary::*; \ No newline at end of file +pub use self::semary::*; diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index 178b2f61..3b7a2146 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -1,18 +1,17 @@ -use lazy_static::lazy_static; -use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; -use crate::sync::SpinLock as Mutex; use crate::sync::Semaphore; -use spin::RwLock; +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 spin::RwLock; pub trait SemArrTrait { - //fn new(key: usize, sems: Vec) -> SemArray; fn get_x(&self, x: usize) -> &Semaphore; } pub struct SemArray { pub key: usize, - pub sems: Vec + pub sems: Vec, } unsafe impl Sync for SemArray {} @@ -22,14 +21,13 @@ impl SemArray { pub fn new(key: usize, sems: Vec) -> SemArray { SemArray { key: key, - sems: sems + sems: sems, } } } impl SemArrTrait for SemArray { fn get_x(&self, x: usize) -> &Semaphore { - //unsafe { &mut self.sems.get()}; &self.sems[x] } } @@ -43,12 +41,12 @@ pub struct SemBuf { pub struct SemUndo { pub sem_id: i16, pub sem_num: i16, - pub sem_op: i16 + pub sem_op: i16, } pub union SemctlUnion { pub val: isize, - pub buf: usize, // semid_ds*, unimplemented + pub buf: usize, // semid_ds*, unimplemented pub array: usize, // short*, unimplemented } // unused @@ -72,8 +70,8 @@ pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc { 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 + sem_array_ref = key2sem_table.get(&key).unwrap().upgrade().unwrap(); // no security check } sem_array_ref -} \ No newline at end of file +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index f36d4f10..994f331d 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -32,6 +32,7 @@ pub mod backtrace; pub mod consts; pub mod drivers; pub mod fs; +pub mod ipc; pub mod lang; pub mod lkm; pub mod memory; @@ -41,7 +42,6 @@ pub mod shell; pub mod sync; pub mod syscall; pub mod trap; -pub mod ipc; #[allow(dead_code)] #[cfg(target_arch = "x86_64")] diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index cc1ebb55..225e9dc8 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -14,11 +14,11 @@ 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::memory::{ ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, }; use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; -use crate::ipc::{SemArray, SemArrTrait, SemUndo}; use super::abi::{self, ProcInitInfo}; use crate::processor; @@ -429,12 +429,15 @@ impl Process { // 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); + 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) { + match (*sem_op) { 1 => sem_ptr.release(), - 0 => {}, + 0 => {} _ => unimplemented!("Semaphore: semundo.(Not 1)"), } } diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index f0055902..8b13f60a 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -83,11 +83,11 @@ impl Semaphore { /// Modify by k atomically. when wait is false avoid waiting. unused pub fn modify(&self, k: isize, wait: bool) -> Result { - match(k) { + match (k) { k if k > 0 => { *(self.lock.lock()) += k; self.cvar.notify_one(); - }, + } k if k <= 0 => { let mut count = self.lock.lock(); let mut temp_k = k; @@ -105,7 +105,7 @@ impl Semaphore { } } _ => { - return Err(()); //unknown error? + return Err(()); //unknown error? } } Ok(0) diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 13464e9a..deefc78a 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -1,16 +1,15 @@ - -use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; -use crate::sync::SpinLock as Mutex; use crate::sync::Semaphore; -use spin::RwLock; +use crate::sync::SpinLock as Mutex; +use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, sync::Weak, vec::Vec}; 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::new_semary; pub use crate::ipc::SemctlUnion; -pub use crate::ipc::semary::SemArrTrait; use super::*; @@ -23,7 +22,7 @@ impl Syscall<'_> { } let mut proc = self.process(); - let mut semarray_table/*: &mut BTreeMap>*/ = &mut proc.semaphores; + let mut semarray_table = &mut proc.semaphores; let sem_id = (0..) .find(|i| match semarray_table.get(i) { @@ -32,36 +31,35 @@ impl Syscall<'_> { }) .unwrap(); - let mut sem_array : Arc = new_semary(key, nsems, semflg); + let mut sem_array: Arc = new_semary(key, nsems, semflg); semarray_table.insert(sem_id, sem_array); Ok(sem_id) } - pub fn sys_semop(&self, sem_id: usize, sem_ops: *const SemBuf, num_sem_ops: usize) -> SysResult { + 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 mut sem_bufs:Vec = Vec::new(); let sem_ops = unsafe { self.vm().check_read_array(sem_ops, num_sem_ops)? }; - //let mut semarray_table/*: &BTreeMap>*/ = proc.semaphores; - for sembuf in sem_ops.iter() { if (sembuf.sem_flg == (SEMFLAGS::IPC_NOWAIT.bits())) { unimplemented!("Semaphore: semop.IPC_NOWAIT"); } - //let mut semarray_arc: Arc = (*((*semarray_table).get(&sem_id).unwrap())).clone(); - //let mut semarray: &mut SemArray = &mut *semarray_arc; - 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 mut result; - match(sembuf.sem_op) { + match (sembuf.sem_op) { 1 => result = sem_ptr.release(), -1 => result = sem_ptr.acquire(), _ => unimplemented!("Semaphore: semop.(Not 1/-1)"), @@ -75,7 +73,6 @@ impl Syscall<'_> { } val -= sembuf.sem_op; proc.semundos.insert((sem_id, sembuf.sem_num), val); - //unimplemented!("Semaphore: semop.SEM_UNDO"); } } info!("sem_op: {}", sem_ops[0].sem_op); @@ -86,8 +83,7 @@ impl Syscall<'_> { info!("sys_semctl: sem_id: {}", sem_id); let mut proc = self.process(); let sem_array: Arc = proc.get_semarray(sem_id); - let sem_ptr = sem_array.get_x(sem_num as usize); - //let mut sem_ptr: &mut Semaphore = proc.get_semarray(sem_id).get_x(sem_num as usize); + let sem_ptr = sem_array.get_x(sem_num as usize); if (cmd == SEMCTLCMD::SETVAL.bits()) { match (sem_ptr.set(arg)) { @@ -98,7 +94,6 @@ impl Syscall<'_> { return Err(SysError::EUNDEF); } } - } else { unimplemented!("Semaphore: Semctl.(Not setval)"); } @@ -120,4 +115,4 @@ bitflags! { const SETVAL = 16; //const SETALL = 17; } -} \ No newline at end of file +} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 0927de81..face8883 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -18,23 +18,23 @@ use crate::util; pub use self::custom::*; pub use self::fs::*; +pub use self::ipc::*; pub use self::lkm::*; pub use self::mem::*; pub use self::misc::*; pub use self::net::*; pub use self::proc::*; pub use self::time::*; -pub use self::ipc::*; mod custom; mod fs; +mod ipc; mod lkm; mod mem; mod misc; mod net; mod proc; mod time; -mod ipc; #[cfg(feature = "profile")] use alloc::collections::BTreeMap; @@ -264,7 +264,12 @@ impl Syscall<'_> { // sem SYS_SEMGET => self.sys_semget(args[0], args[1], args[2]), SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), - SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3] as isize/* as SemctlUnion*/), + SYS_SEMCTL => self.sys_semctl( + args[0], + args[1], + args[2], + args[3] as isize, /* as SemctlUnion*/ + ), // system SYS_GETPID => self.sys_getpid(), diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 03f15f40..a20fc4fd 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -277,7 +277,7 @@ impl Syscall<'_> { queue.notify_one(); } } - + drop(proc); processor().manager().exit(tid, exit_code as usize); diff --git a/rboot b/rboot index 3546cf87..5aae6587 160000 --- a/rboot +++ b/rboot @@ -1 +1 @@ -Subproject commit 3546cf87ee5aaefc638e6009262358fe07af8717 +Subproject commit 5aae6587f635f9eabd8f4643f381aa48cf597131 diff --git a/user b/user index 894d98f2..5557c941 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 894d98f2163c4a96d4bf1990d83ce143ed558bce +Subproject commit 5557c941083754f9e6c85de9ea3e101693c9f9c7 From a99f4396eba3603378eb85bdf9ad18c1387acfdd Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Thu, 24 Oct 2019 19:44:42 +0800 Subject: [PATCH 11/14] clean and improve code --- kernel/run.sh | 1 - kernel/src/ipc/mod.rs | 2 +- kernel/src/ipc/semary.rs | 86 ++++++++-------------- kernel/src/process/structs.rs | 20 +++--- kernel/src/sync/semaphore.rs | 57 ++++++--------- kernel/src/syscall/ipc.rs | 132 +++++++++++++++------------------- kernel/src/syscall/mod.rs | 2 +- 7 files changed, 117 insertions(+), 183 deletions(-) delete mode 100755 kernel/run.sh diff --git a/kernel/run.sh b/kernel/run.sh deleted file mode 100755 index 911a43e0..00000000 --- a/kernel/run.sh +++ /dev/null @@ -1 +0,0 @@ -make run arch=x86_64 diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index dced3002..6b743bb7 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,3 +1,3 @@ -pub mod semary; +mod semary; pub use self::semary::*; diff --git a/kernel/src/ipc/semary.rs b/kernel/src/ipc/semary.rs index 3b7a2146..b54511af 100644 --- a/kernel/src/ipc/semary.rs +++ b/kernel/src/ipc/semary.rs @@ -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, + key: usize, + sems: Vec, } -unsafe impl Sync for SemArray {} -unsafe impl Send for SemArray {} - -impl SemArray { - pub fn new(key: usize, sems: Vec) -> SemArray { - SemArray { - key: key, - sems: sems, - } +impl Index 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>> = - RwLock::new(BTreeMap::new()); // not mentioned. + static ref KEY2SEM: RwLock>> = RwLock::new(BTreeMap::new()); } -pub fn new_semary(key: usize, nsems: usize, semflg: usize) -> Arc { - let mut key2sem_table = KEY2SEM.write(); - let mut sem_array_ref: Arc; +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 { + 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 = 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 } diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 225e9dc8..5498c68f 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -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 { - self.semaphores.get(&uaddr).unwrap().clone() + pub fn get_semarray(&mut self, id: usize) -> Arc { + 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)"), diff --git a/kernel/src/sync/semaphore.rs b/kernel/src/sync/semaphore.rs index 8b13f60a..be7927c4 100644 --- a/kernel/src/sync/semaphore.rs +++ b/kernel/src/sync/semaphore.rs @@ -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 { + /// Get the current count + pub fn get(&self) -> isize { let mut count = self.lock.lock(); - Ok((*count) >= k) + *count } - pub fn get(&self) -> Result { + /// 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 { - 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) } diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index deefc78a..43f24066 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -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 = 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 = proc.get_semarray(sem_id); - let sem_ptr = sem_array.get_x(sem_num as usize); + let sem_array: Arc = 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; - } -} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index face8883..37766b6b 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -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], From b7a192a1ea035f7223b0ad2a2fadaada29dfa66c Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Thu, 24 Oct 2019 20:33:00 +0800 Subject: [PATCH 12/14] move all process related semaphore operations to struct SemProc --- kernel/src/ipc/mod.rs | 69 +++++++++++++++++++++++++++++++++++ kernel/src/process/structs.rs | 28 ++------------ kernel/src/syscall/ipc.rs | 24 +++++------- 3 files changed, 83 insertions(+), 38 deletions(-) diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 6b743bb7..879a0d9c 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -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>, + /// 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) -> 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> { + 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)"), + } + } + } +} diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 5498c68f..2e0eb411 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -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>, - pub semaphores: BTreeMap>, - 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 { - 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); diff --git a/kernel/src/syscall/ipc.rs b/kernel/src/syscall/ipc.rs index 43f24066..c9956f3b 100644 --- a/kernel/src/syscall/ipc.rs +++ b/kernel/src/syscall/ipc.rs @@ -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 = 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; } } From 71fa6a3012a676b78fef99e8cce1922dbffdc3aa Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Thu, 24 Oct 2019 20:34:16 +0800 Subject: [PATCH 13/14] fix user submodule --- user | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user b/user index 5557c941..3ae3a840 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 5557c941083754f9e6c85de9ea3e101693c9f9c7 +Subproject commit 3ae3a840bf39bbd6628892842688c8720273546d From d4702faa0ff6b3f7283056297bc2e916d10baa2f Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Sat, 26 Oct 2019 11:29:27 +0800 Subject: [PATCH 14/14] fix SYS_IPC on mips --- kernel/src/syscall/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 37766b6b..b07caf78 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -262,14 +262,12 @@ impl Syscall<'_> { SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec), // sem + #[cfg(not(target_arch = "mips"))] SYS_SEMGET => self.sys_semget(args[0], args[1] as isize, args[2]), + #[cfg(not(target_arch = "mips"))] SYS_SEMOP => self.sys_semop(args[0], args[1] as *const SemBuf, args[2]), - SYS_SEMCTL => self.sys_semctl( - args[0], - args[1], - args[2], - args[3] as isize, /* as SemctlUnion*/ - ), + #[cfg(not(target_arch = "mips"))] + SYS_SEMCTL => self.sys_semctl(args[0], args[1], args[2], args[3] as isize), // system SYS_GETPID => self.sys_getpid(), @@ -410,6 +408,12 @@ impl Syscall<'_> { } Ok(0) } + SYS_IPC => match args[0] { + 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]), + 3 => self.sys_semctl(args[1], args[2], args[3], args[4] as isize), + _ => return None, + }, _ => return None, }; Some(ret)