add syscall rt_procmask

This commit is contained in:
Jianfeng Jiang
2022-11-02 15:16:37 +08:00
parent f86cd1e6bc
commit 149f72e31f
16 changed files with 162 additions and 26 deletions

2
.gitattributes vendored
View File

@ -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/execve filter=lfs diff=lfs merge=lfs -text
src/kxos-user/execve/hello 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/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

View File

@ -5,17 +5,19 @@ pub struct SigMask {
bits: u64, bits: u64,
} }
impl SigMask { impl From<u64> for SigMask {
pub const fn from_u64(bits: u64) -> Self { fn from(bits: u64) -> Self {
SigMask { bits } SigMask { bits }
} }
}
pub const fn new_empty() -> Self { impl SigMask {
SigMask::from_u64(0) pub fn new_empty() -> Self {
SigMask::from(0u64)
} }
pub const fn new_full() -> Self { pub fn new_full() -> Self {
SigMask::from_u64(!0) SigMask::from(!0u64)
} }
pub const fn as_u64(&self) -> u64 { pub const fn as_u64(&self) -> u64 {
@ -30,6 +32,18 @@ impl SigMask {
self.bits == !0 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 { pub fn count(&self) -> usize {
self.bits.count_ones() as usize self.bits.count_ones() as usize
} }

View File

@ -1,15 +1,27 @@
use super::constants::*; use super::constants::*;
use crate::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SigNum { pub struct SigNum {
sig_num: u8, sig_num: u8,
} }
impl TryFrom<u8> for SigNum {
type Error = Error;
fn try_from(sig_num: u8) -> Result<Self> {
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 { 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 { pub const fn from_u8(sig_num: u8) -> Self {
if sig_num > MAX_RT_SIG_NUM || sig_num < MIN_STD_SIG_NUM { if sig_num > MAX_RT_SIG_NUM || sig_num < MIN_STD_SIG_NUM {
unreachable!() panic!("invalid signal number")
} }
SigNum { sig_num } SigNum { sig_num }
} }

View File

@ -106,7 +106,7 @@ impl SigQueues {
// process, they are delivered starting with the lowest-numbered // process, they are delivered starting with the lowest-numbered
// signal. (I.e., low-numbered signals have highest priority.) // signal. (I.e., low-numbered signals have highest priority.)
for signum in MIN_RT_SIG_NUM..=MAX_RT_SIG_NUM { 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) { if blocked.contains(signum) {
continue; continue;
} }

View File

@ -5,10 +5,10 @@ use crate::prelude::*;
use crate::syscall::{SyscallResult, SYS_FSTAT}; 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!("[syscall][id={}][SYS_FSTAT]", SYS_FSTAT);
debug!("fd = {}", fd); 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 current = current!();
let vm_space = current let vm_space = current
@ -17,7 +17,7 @@ pub fn sys_fstat(fd: u64, stat_buf_addr: Vaddr) -> SyscallResult {
if fd == 1 { if fd == 1 {
let stat = Stat::stdout_stat(); let stat = Stat::stdout_stat();
vm_space vm_space
.write_val(stat_buf_addr, &stat) .write_val(stat_buf_ptr, &stat)
.expect("Write value failed"); .expect("Write value failed");
return SyscallResult::Return(0); return SyscallResult::Return(0);
} }

View File

@ -12,7 +12,7 @@ use super::SyscallResult;
pub fn sys_kill(process_filter: u64, sig_num: u64) -> SyscallResult { pub fn sys_kill(process_filter: u64, sig_num: u64) -> SyscallResult {
debug!("[syscall][id={}][SYS_KILL]", SYS_KILL); debug!("[syscall][id={}][SYS_KILL]", SYS_KILL);
let process_filter = ProcessFilter::from_id(process_filter as _); 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); let _ = do_sys_kill(process_filter, sig_num);
SyscallResult::Return(0) SyscallResult::Return(0)
} }

View File

@ -4,6 +4,7 @@
use crate::prelude::*; use crate::prelude::*;
use crate::syscall::clone::sys_clone; use crate::syscall::clone::sys_clone;
use crate::syscall::kill::sys_kill; use crate::syscall::kill::sys_kill;
use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask;
use alloc::borrow::ToOwned; use alloc::borrow::ToOwned;
use kxos_frame::cpu::CpuContext; use kxos_frame::cpu::CpuContext;
@ -52,6 +53,7 @@ mod wait4;
mod waitid; mod waitid;
mod write; mod write;
mod writev; mod writev;
mod rt_sigprocmask;
const SYS_WRITE: u64 = 1; const SYS_WRITE: u64 = 1;
const SYS_FSTAT: u64 = 5; const SYS_FSTAT: u64 = 5;
@ -133,7 +135,7 @@ pub fn syscall_dispatch(
SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]), SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]),
SYS_BRK => sys_brk(args[0]), SYS_BRK => sys_brk(args[0]),
SYS_RT_SIGACTION => sys_rt_sigaction(), 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_WRITEV => sys_writev(args[0], args[1], args[2]),
SYS_ACCESS => sys_access(args[0] as _, args[1]), SYS_ACCESS => sys_access(args[0] as _, args[1]),
SYS_GETPID => sys_getpid(), SYS_GETPID => sys_getpid(),
@ -172,12 +174,6 @@ pub fn sys_rt_sigaction() -> SyscallResult {
SyscallResult::Return(0) 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 { pub fn sys_getuid() -> SyscallResult {
debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID); debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID);
warn!("TODO: getuid only return a fake uid now"); warn!("TODO: getuid only return a fake uid now");

View File

@ -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::<u64>(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<u32> for MaskOp {
type Error = Error;
fn try_from(value: u32) -> Result<Self> {
let op = match value {
0 => MaskOp::Block,
1 => MaskOp::Unblock,
2 => MaskOp::SetMask,
_ => return_errno_with_message!(Errno::EINVAL, "invalid mask op"),
};
Ok(op)
}
}

View File

@ -16,19 +16,19 @@ pub struct IoVec {
len: usize, 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); 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 _) 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!("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); debug!("io_vec_counter = 0x{:x}", io_vec_count);
let mut write_len = 0; let mut write_len = 0;
for i in 0..io_vec_count { for i in 0..io_vec_count {
let io_vec = read_val_from_user::<IoVec>(io_vec_addr + i * 8); let io_vec = read_val_from_user::<IoVec>(io_vec_ptr + i * 8);
let base = io_vec.base; let base = io_vec.base;
let len = io_vec.len; let len = io_vec.len;
debug!("base = 0x{:x}", base); debug!("base = 0x{:x}", base);

View File

@ -24,7 +24,7 @@ impl UserApp {
} }
pub fn get_all_apps() -> Vec<UserApp> { pub fn get_all_apps() -> Vec<UserApp> {
let mut res = Vec::new(); let mut res = Vec::with_capacity(16);
// Most simple hello world, written in assembly // Most simple hello world, written in assembly
let app1 = UserApp::new("hello_world", read_hello_world_content()); let app1 = UserApp::new("hello_world", read_hello_world_content());
@ -48,6 +48,10 @@ pub fn get_all_apps() -> Vec<UserApp> {
let app5 = UserApp::new("/fork", read_fork_c_content()); let app5 = UserApp::new("/fork", read_fork_c_content());
res.push(app5); res.push(app5);
// Set sig procmask
let app6 = UserApp::new("/sig_procmask", read_sig_procmask());
res.push(app6);
res res
} }
@ -74,3 +78,7 @@ pub fn read_execve_hello_content() -> &'static [u8] {
fn read_fork_c_content() -> &'static [u8] { fn read_fork_c_content() -> &'static [u8] {
include_bytes!("../../kxos-user/fork_c/fork") include_bytes!("../../kxos-user/fork_c/fork")
} }
fn read_sig_procmask() -> &'static [u8] {
include_bytes!("../../kxos-user/signal_c/sig_procmask")
}

View File

@ -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

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:07eb07c6387a9afd68a5b8a8bba9b48e1362b9c3b8f18ce30e744640a4dfa546
size 871776

View File

@ -0,0 +1,7 @@
#include<stdio.h>
int main() {
int a = 2 - 2;
int b = 1 / a;
return 0;
}

View File

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6faf986f058a2480297fb323a536319f9c7dde76efe4ed0472f09a4ad2960c9b
size 871848

View File

@ -0,0 +1,19 @@
/// This code is from CSAPP
/// We use this codes to test sigprocmask
#include <stdio.h>
#include <signal.h>
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;
}