From 149f72e31f057d301ce2b730c6c18f7997afa28b Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Wed, 2 Nov 2022 15:16:37 +0800 Subject: [PATCH] add syscall rt_procmask --- .gitattributes | 2 + src/kxos-std/src/process/signal/sig_mask.rs | 26 ++++++-- src/kxos-std/src/process/signal/sig_num.rs | 16 ++++- src/kxos-std/src/process/signal/sig_queues.rs | 2 +- src/kxos-std/src/syscall/fstat.rs | 6 +- src/kxos-std/src/syscall/kill.rs | 2 +- src/kxos-std/src/syscall/mod.rs | 10 +-- src/kxos-std/src/syscall/rt_sigprocmask.rs | 63 +++++++++++++++++++ src/kxos-std/src/syscall/writev.rs | 10 +-- src/kxos-std/src/user_apps.rs | 10 ++- src/kxos-user/signal_c/Makefile | 9 +++ src/kxos-user/signal_c/divide_zero | 3 + src/kxos-user/signal_c/divide_zero.c | 7 +++ src/kxos-user/signal_c/sig_action.c | 0 src/kxos-user/signal_c/sig_procmask | 3 + src/kxos-user/signal_c/sig_procmask.c | 19 ++++++ 16 files changed, 162 insertions(+), 26 deletions(-) create mode 100644 src/kxos-std/src/syscall/rt_sigprocmask.rs create mode 100644 src/kxos-user/signal_c/Makefile create mode 100755 src/kxos-user/signal_c/divide_zero create mode 100644 src/kxos-user/signal_c/divide_zero.c create mode 100644 src/kxos-user/signal_c/sig_action.c create mode 100755 src/kxos-user/signal_c/sig_procmask create mode 100644 src/kxos-user/signal_c/sig_procmask.c diff --git a/.gitattributes b/.gitattributes index 96915b308..39e2684c8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,5 @@ src/kxos-user/hello_c/hello filter=lfs diff=lfs merge=lfs -text src/kxos-user/execve/execve filter=lfs diff=lfs merge=lfs -text src/kxos-user/execve/hello filter=lfs diff=lfs merge=lfs -text src/kxos-user/fork_c/fork filter=lfs diff=lfs merge=lfs -text +src/kxos-user/signal_c/divide_zero filter=lfs diff=lfs merge=lfs -text +src/kxos-user/signal_c/sig_procmask filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/src/kxos-std/src/process/signal/sig_mask.rs b/src/kxos-std/src/process/signal/sig_mask.rs index 0b0d998f2..301cc9f90 100644 --- a/src/kxos-std/src/process/signal/sig_mask.rs +++ b/src/kxos-std/src/process/signal/sig_mask.rs @@ -5,17 +5,19 @@ pub struct SigMask { bits: u64, } -impl SigMask { - pub const fn from_u64(bits: u64) -> Self { +impl From for SigMask { + fn from(bits: u64) -> Self { SigMask { bits } } +} - pub const fn new_empty() -> Self { - SigMask::from_u64(0) +impl SigMask { + pub fn new_empty() -> Self { + SigMask::from(0u64) } - pub const fn new_full() -> Self { - SigMask::from_u64(!0) + pub fn new_full() -> Self { + SigMask::from(!0u64) } pub const fn as_u64(&self) -> u64 { @@ -30,6 +32,18 @@ impl SigMask { self.bits == !0 } + pub fn block(&mut self, block_sets: u64) { + self.bits |= block_sets; + } + + pub fn unblock(&mut self, unblock_sets: u64) { + self.bits &= !unblock_sets; + } + + pub fn set(&mut self, new_set:u64) { + self.bits = new_set; + } + pub fn count(&self) -> usize { self.bits.count_ones() as usize } diff --git a/src/kxos-std/src/process/signal/sig_num.rs b/src/kxos-std/src/process/signal/sig_num.rs index 1facf40ab..27963f9ee 100644 --- a/src/kxos-std/src/process/signal/sig_num.rs +++ b/src/kxos-std/src/process/signal/sig_num.rs @@ -1,15 +1,27 @@ use super::constants::*; +use crate::prelude::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct SigNum { sig_num: u8, } +impl TryFrom for SigNum { + type Error = Error; + + fn try_from(sig_num: u8) -> Result { + if sig_num > MAX_RT_SIG_NUM || sig_num < MIN_STD_SIG_NUM { + return_errno_with_message!(Errno::EINVAL, "invalid signal number"); + } + Ok(SigNum { sig_num }) + } +} + impl SigNum { - // Safety: This function should only be used when signum is ensured to be valid. + /// Caller must ensure the sig_num is valid. otherweise, use try_from will check sig_num and does not panic. pub const fn from_u8(sig_num: u8) -> Self { if sig_num > MAX_RT_SIG_NUM || sig_num < MIN_STD_SIG_NUM { - unreachable!() + panic!("invalid signal number") } SigNum { sig_num } } diff --git a/src/kxos-std/src/process/signal/sig_queues.rs b/src/kxos-std/src/process/signal/sig_queues.rs index eef4db07b..7918daa8f 100644 --- a/src/kxos-std/src/process/signal/sig_queues.rs +++ b/src/kxos-std/src/process/signal/sig_queues.rs @@ -106,7 +106,7 @@ impl SigQueues { // process, they are delivered starting with the lowest-numbered // signal. (I.e., low-numbered signals have highest priority.) for signum in MIN_RT_SIG_NUM..=MAX_RT_SIG_NUM { - let signum = SigNum::from_u8(signum); + let signum = SigNum::try_from(signum).unwrap(); if blocked.contains(signum) { continue; } diff --git a/src/kxos-std/src/syscall/fstat.rs b/src/kxos-std/src/syscall/fstat.rs index 3cf237b50..1581ad7c4 100644 --- a/src/kxos-std/src/syscall/fstat.rs +++ b/src/kxos-std/src/syscall/fstat.rs @@ -5,10 +5,10 @@ use crate::prelude::*; use crate::syscall::{SyscallResult, SYS_FSTAT}; -pub fn sys_fstat(fd: u64, stat_buf_addr: Vaddr) -> SyscallResult { +pub fn sys_fstat(fd: u64, stat_buf_ptr: Vaddr) -> SyscallResult { debug!("[syscall][id={}][SYS_FSTAT]", SYS_FSTAT); debug!("fd = {}", fd); - debug!("stat_buf_addr = 0x{:x}", stat_buf_addr); + debug!("stat_buf_addr = 0x{:x}", stat_buf_ptr); let current = current!(); let vm_space = current @@ -17,7 +17,7 @@ pub fn sys_fstat(fd: u64, stat_buf_addr: Vaddr) -> SyscallResult { if fd == 1 { let stat = Stat::stdout_stat(); vm_space - .write_val(stat_buf_addr, &stat) + .write_val(stat_buf_ptr, &stat) .expect("Write value failed"); return SyscallResult::Return(0); } diff --git a/src/kxos-std/src/syscall/kill.rs b/src/kxos-std/src/syscall/kill.rs index e4af4f220..96ab2bac3 100644 --- a/src/kxos-std/src/syscall/kill.rs +++ b/src/kxos-std/src/syscall/kill.rs @@ -12,7 +12,7 @@ use super::SyscallResult; pub fn sys_kill(process_filter: u64, sig_num: u64) -> SyscallResult { debug!("[syscall][id={}][SYS_KILL]", SYS_KILL); let process_filter = ProcessFilter::from_id(process_filter as _); - let sig_num = SigNum::from_u8(sig_num as _); + let sig_num = SigNum::try_from(sig_num as u8).unwrap(); let _ = do_sys_kill(process_filter, sig_num); SyscallResult::Return(0) } diff --git a/src/kxos-std/src/syscall/mod.rs b/src/kxos-std/src/syscall/mod.rs index 64e283354..1c17291a0 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -4,6 +4,7 @@ use crate::prelude::*; use crate::syscall::clone::sys_clone; use crate::syscall::kill::sys_kill; +use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask; use alloc::borrow::ToOwned; use kxos_frame::cpu::CpuContext; @@ -52,6 +53,7 @@ mod wait4; mod waitid; mod write; mod writev; +mod rt_sigprocmask; const SYS_WRITE: u64 = 1; const SYS_FSTAT: u64 = 5; @@ -133,7 +135,7 @@ pub fn syscall_dispatch( SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]), SYS_BRK => sys_brk(args[0]), SYS_RT_SIGACTION => sys_rt_sigaction(), - SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(), + SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(args[0] as _, args[1] as _, args[2] as _, args[3] as _), SYS_WRITEV => sys_writev(args[0], args[1], args[2]), SYS_ACCESS => sys_access(args[0] as _, args[1]), SYS_GETPID => sys_getpid(), @@ -172,12 +174,6 @@ pub fn sys_rt_sigaction() -> SyscallResult { SyscallResult::Return(0) } -pub fn sys_rt_sigprocmask() -> SyscallResult { - debug!("[syscall][id={}][SYS_RT_SIGPROCMASK]", SYS_RT_SIGPROCMASK); - warn!("TODO: rt_sigprocmask only return a fake result"); - SyscallResult::Return(0) -} - pub fn sys_getuid() -> SyscallResult { debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID); warn!("TODO: getuid only return a fake uid now"); diff --git a/src/kxos-std/src/syscall/rt_sigprocmask.rs b/src/kxos-std/src/syscall/rt_sigprocmask.rs new file mode 100644 index 000000000..2da276635 --- /dev/null +++ b/src/kxos-std/src/syscall/rt_sigprocmask.rs @@ -0,0 +1,63 @@ +use kxos_frame::vm::VmIo; + +use crate::{prelude::*, syscall::SYS_RT_SIGPROCMASK}; + +use super::SyscallResult; +pub fn sys_rt_sigprocmask(how: u32, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_size: usize) -> SyscallResult { + debug!("[syscall][id={}][SYS_RT_SIGPROCMASK]", SYS_RT_SIGPROCMASK); + let mask_op = MaskOp::try_from(how).unwrap(); + debug!("mask op = {:?}", mask_op); + debug!("set_ptr = 0x{:x}", set_ptr); + debug!("oldset_ptr = 0x{:x}", oldset_ptr); + debug!("sigset_size = {}", sigset_size); + if sigset_size != 8 { + warn!("sigset size is not equal to 8"); + } + do_rt_sigprocmask(mask_op, set_ptr, oldset_ptr, sigset_size).unwrap(); + SyscallResult::Return(0) +} + +fn do_rt_sigprocmask(mask_op: MaskOp, set_ptr: Vaddr, oldset_ptr: Vaddr, sigset_size: usize) -> Result<()>{ + let current = current!(); + let vm_space = current.vm_space().unwrap(); + let mut sig_mask = current.sig_mask().lock(); + let old_sig_mask_value = sig_mask.as_u64(); + debug!("old sig mask value: 0x{:x}", old_sig_mask_value); + if oldset_ptr != 0 { + vm_space.write_val(oldset_ptr, &old_sig_mask_value)?; + } + if set_ptr != 0 { + let new_set = vm_space.read_val::(set_ptr)?; + debug!("new set = 0x{:x}", new_set); + match mask_op { + MaskOp::Block => sig_mask.block(new_set ), + MaskOp::Unblock => sig_mask.unblock(new_set), + MaskOp::SetMask => sig_mask.set(new_set), + } + } + debug!("new set = {:x?}", &sig_mask); + + Ok(()) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum MaskOp { + Block = 0, + Unblock = 1, + SetMask = 2, +} + +impl TryFrom for MaskOp { + type Error = Error; + + fn try_from(value: u32) -> Result { + let op = match value { + 0 => MaskOp::Block, + 1 => MaskOp::Unblock, + 2 => MaskOp::SetMask, + _ => return_errno_with_message!(Errno::EINVAL, "invalid mask op"), + }; + Ok(op) + } +} \ No newline at end of file diff --git a/src/kxos-std/src/syscall/writev.rs b/src/kxos-std/src/syscall/writev.rs index 1e66efc51..ae3c1d9f9 100644 --- a/src/kxos-std/src/syscall/writev.rs +++ b/src/kxos-std/src/syscall/writev.rs @@ -16,19 +16,19 @@ pub struct IoVec { len: usize, } -pub fn sys_writev(fd: u64, io_vec_addr: u64, io_vec_count: u64) -> SyscallResult { +pub fn sys_writev(fd: u64, io_vec_ptr: u64, io_vec_count: u64) -> SyscallResult { debug!("[syscall][id={}][SYS_WRITEV]", SYS_WRITEV); - let res = do_sys_writev(fd, io_vec_addr as Vaddr, io_vec_count as usize); + let res = do_sys_writev(fd, io_vec_ptr as Vaddr, io_vec_count as usize); SyscallResult::Return(res as _) } -pub fn do_sys_writev(fd: u64, io_vec_addr: Vaddr, io_vec_count: usize) -> usize { +pub fn do_sys_writev(fd: u64, io_vec_ptr: Vaddr, io_vec_count: usize) -> usize { debug!("fd = {}", fd); - debug!("io_vec_addr = 0x{:x}", io_vec_addr); + debug!("io_vec_ptr = 0x{:x}", io_vec_ptr); debug!("io_vec_counter = 0x{:x}", io_vec_count); let mut write_len = 0; for i in 0..io_vec_count { - let io_vec = read_val_from_user::(io_vec_addr + i * 8); + let io_vec = read_val_from_user::(io_vec_ptr + i * 8); let base = io_vec.base; let len = io_vec.len; debug!("base = 0x{:x}", base); diff --git a/src/kxos-std/src/user_apps.rs b/src/kxos-std/src/user_apps.rs index 813cd286a..f91fe1360 100644 --- a/src/kxos-std/src/user_apps.rs +++ b/src/kxos-std/src/user_apps.rs @@ -24,7 +24,7 @@ impl UserApp { } pub fn get_all_apps() -> Vec { - let mut res = Vec::new(); + let mut res = Vec::with_capacity(16); // Most simple hello world, written in assembly let app1 = UserApp::new("hello_world", read_hello_world_content()); @@ -48,6 +48,10 @@ pub fn get_all_apps() -> Vec { let app5 = UserApp::new("/fork", read_fork_c_content()); res.push(app5); + // Set sig procmask + let app6 = UserApp::new("/sig_procmask", read_sig_procmask()); + res.push(app6); + res } @@ -74,3 +78,7 @@ pub fn read_execve_hello_content() -> &'static [u8] { fn read_fork_c_content() -> &'static [u8] { include_bytes!("../../kxos-user/fork_c/fork") } + +fn read_sig_procmask() -> &'static [u8] { + include_bytes!("../../kxos-user/signal_c/sig_procmask") +} diff --git a/src/kxos-user/signal_c/Makefile b/src/kxos-user/signal_c/Makefile new file mode 100644 index 000000000..bc903b97f --- /dev/null +++ b/src/kxos-user/signal_c/Makefile @@ -0,0 +1,9 @@ +.PHONY: build clean run +build: divide_zero.c sig_procmask.c + @gcc -static divide_zero.c -o divide_zero + @gcc -static sig_procmask.c -o sig_procmask +clean: + @rm divide_zero sig_procmask +run: build + @./sig_procmask + @./divide_zero diff --git a/src/kxos-user/signal_c/divide_zero b/src/kxos-user/signal_c/divide_zero new file mode 100755 index 000000000..cad40895a --- /dev/null +++ b/src/kxos-user/signal_c/divide_zero @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07eb07c6387a9afd68a5b8a8bba9b48e1362b9c3b8f18ce30e744640a4dfa546 +size 871776 diff --git a/src/kxos-user/signal_c/divide_zero.c b/src/kxos-user/signal_c/divide_zero.c new file mode 100644 index 000000000..15be02cfe --- /dev/null +++ b/src/kxos-user/signal_c/divide_zero.c @@ -0,0 +1,7 @@ +#include + +int main() { + int a = 2 - 2; + int b = 1 / a; + return 0; +} \ No newline at end of file diff --git a/src/kxos-user/signal_c/sig_action.c b/src/kxos-user/signal_c/sig_action.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/kxos-user/signal_c/sig_procmask b/src/kxos-user/signal_c/sig_procmask new file mode 100755 index 000000000..845c7aeb7 --- /dev/null +++ b/src/kxos-user/signal_c/sig_procmask @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6faf986f058a2480297fb323a536319f9c7dde76efe4ed0472f09a4ad2960c9b +size 871848 diff --git a/src/kxos-user/signal_c/sig_procmask.c b/src/kxos-user/signal_c/sig_procmask.c new file mode 100644 index 000000000..3cd034bf0 --- /dev/null +++ b/src/kxos-user/signal_c/sig_procmask.c @@ -0,0 +1,19 @@ +/// This code is from CSAPP +/// We use this codes to test sigprocmask +#include +#include + +int main() { + sigset_t mask, prev_mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGCHLD); + + /* Block SIGINT and save previous blocked set */ + sigprocmask(SIG_BLOCK, &mask, &prev_mask); + + // Code region that will not be interrupted by SIGINT and SIGCHILD + /* Restore previous blocked set, unblocking SIGINT */ + sigprocmask(SIG_SETMASK, &prev_mask, NULL); + return 0; +} \ No newline at end of file