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

View File

@ -5,17 +5,19 @@ pub struct SigMask {
bits: u64,
}
impl SigMask {
pub const fn from_u64(bits: u64) -> Self {
impl From<u64> for SigMask {
fn from(bits: u64) -> Self {
SigMask { bits }
}
pub const fn new_empty() -> Self {
SigMask::from_u64(0)
}
pub const fn new_full() -> Self {
SigMask::from_u64(!0)
impl SigMask {
pub fn new_empty() -> Self {
SigMask::from(0u64)
}
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
}

View File

@ -1,15 +1,27 @@
use super::constants::*;
use crate::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SigNum {
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 {
// 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 }
}

View File

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

View File

@ -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);
}

View File

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

View File

@ -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");

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,
}
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::<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 len = io_vec.len;
debug!("base = 0x{:x}", base);

View File

@ -24,7 +24,7 @@ impl 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
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());
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")
}

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;
}