forked from rcore-os/zCore
Merge lsm-yzc-merge
This commit is contained in:
commit
b51c8ebea3
|
@ -1,6 +1,6 @@
|
|||
[submodule "rboot"]
|
||||
path = rboot
|
||||
url = https://github.com/rcore-os/rboot.git
|
||||
url = https://github.91chi.fun//https://github.com/rcore-os/rboot.git
|
||||
[submodule "tests"]
|
||||
path = tests
|
||||
url = https://github.com/rcore-os/zcore-tests.git
|
||||
url = https://github.91chi.fun//https://github.com/rcore-os/zcore-tests.git
|
||||
|
|
|
@ -43,4 +43,4 @@ x2apic = "0.4"
|
|||
x86_64 = "0.14"
|
||||
|
||||
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
||||
riscv = { git = "https://github.com/rust-embedded/riscv", rev = "cd31989", features = ["inline-asm"] }
|
||||
riscv = { git = "https://github.91chi.fun//https://github.com/rust-embedded/riscv", rev = "cd31989", features = ["inline-asm"] }
|
|
@ -33,7 +33,7 @@ smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-fe
|
|||
nix = { version = "0.23", optional = true }
|
||||
tempfile = { version = "3", optional = true }
|
||||
async-std = { version = "1.10", optional = true }
|
||||
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "b3f9f51", optional = true }
|
||||
bitmap-allocator = { git = "https://github.91chi.fun//https://github.com/rcore-os/bitmap-allocator.git", rev = "b3f9f51", optional = true }
|
||||
|
||||
# Bare-metal mode
|
||||
[target.'cfg(target_os = "none")'.dependencies]
|
||||
|
@ -49,7 +49,7 @@ x86_64 = "0.14"
|
|||
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
|
||||
uefi = "0.11"
|
||||
raw-cpuid = "9.0"
|
||||
x86-smpboot = { git = "https://github.com/rcore-os/x86-smpboot", rev = "1069df3" }
|
||||
x86-smpboot = { git = "https://github.91chi.fun//https://github.com/rcore-os/x86-smpboot", rev = "1069df3" }
|
||||
|
||||
# Bare-metal mode on riscv64
|
||||
[target.'cfg(all(target_os = "none", target_arch = "riscv64"))'.dependencies]
|
||||
|
|
|
@ -116,7 +116,7 @@ impl TrapReason {
|
|||
|
||||
/// User context saved on trap.
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct UserContext(UserContextInner);
|
||||
|
||||
impl UserContext {
|
||||
|
@ -127,35 +127,53 @@ impl UserContext {
|
|||
}
|
||||
|
||||
/// Initialize the context for entry into userspace.
|
||||
pub fn setup_uspace(&mut self, pc: usize, sp: usize, arg1: usize, arg2: usize) {
|
||||
/// Note: if the number of args < 3, please fill with zeros
|
||||
/// Eg: ctx.setup_uspace(pc_, sp_, &[arg1, arg2, 0])
|
||||
pub fn setup_uspace(&mut self, pc: usize, sp: usize, args: &[usize; 3]) {
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")] {
|
||||
self.0.general.rip = pc;
|
||||
self.0.general.rsp = sp;
|
||||
self.0.general.rdi = arg1;
|
||||
self.0.general.rsi = arg2;
|
||||
self.0.general.rdi = args[0];
|
||||
self.0.general.rsi = args[1];
|
||||
self.0.general.rdx = args[2];
|
||||
// IOPL = 3, IF = 1
|
||||
// FIXME: set IOPL = 0 when IO port bitmap is supporte
|
||||
self.0.general.rflags = 0x3000 | 0x200 | 0x2;
|
||||
} else if #[cfg(target_arch = "aarch64")] {
|
||||
self.0.elr = pc;
|
||||
self.0.sp = sp;
|
||||
self.0.general.x0 = arg1;
|
||||
self.0.general.x1 = arg2;
|
||||
self.0.general.x0 = args[0];
|
||||
self.0.general.x1 = args[1];
|
||||
self.0.general.x2 = args[2];
|
||||
// Mask SError exceptions (currently unhandled).
|
||||
// TODO
|
||||
self.0.spsr = 1 << 8;
|
||||
} else if #[cfg(target_arch = "riscv64")] {
|
||||
self.0.sepc = pc;
|
||||
self.0.general.sp = sp;
|
||||
self.0.general.a0 = arg1;
|
||||
self.0.general.a1 = arg2;
|
||||
self.0.general.a0 = args[0];
|
||||
self.0.general.a1 = args[1];
|
||||
self.0.general.a2 = args[2];
|
||||
// SUM = 1, FS = 0b11, SPIE = 1
|
||||
self.0.sstatus = 1 << 18 | 0b11 << 13 | 1 << 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Setup return addr
|
||||
pub fn set_ra(&mut self, _ra: usize) {
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "riscv64")] {
|
||||
self.0.general.ra = _ra;
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
error!("Please set return addr via stack!");
|
||||
} else {
|
||||
unimplemented!("Unsupported arch!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Switch to user mode.
|
||||
pub fn enter_uspace(&mut self) {
|
||||
cfg_if! {
|
||||
|
|
|
@ -111,6 +111,8 @@ pub enum LxError {
|
|||
EISCONN = 106,
|
||||
/// Transport endpoint is not connected
|
||||
ENOTCONN = 107,
|
||||
/// Connection timeout
|
||||
ETIMEDOUT = 110,
|
||||
/// Connection refused
|
||||
ECONNREFUSED = 111,
|
||||
}
|
||||
|
@ -184,6 +186,7 @@ impl From<ZxError> for LxError {
|
|||
ZxError::SHOULD_WAIT => LxError::EAGAIN,
|
||||
ZxError::PEER_CLOSED => LxError::EPIPE,
|
||||
ZxError::BAD_HANDLE => LxError::EBADF,
|
||||
ZxError::TIMED_OUT => LxError::ETIMEDOUT,
|
||||
_ => unimplemented!("unknown error type: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,9 @@ pub fn create_root_fs(rootfs: Arc<dyn FileSystem>) -> Arc<dyn INode> {
|
|||
devfs_root
|
||||
.add("urandom", Arc::new(RandomINode::new(true)))
|
||||
.expect("failed to mknod /dev/urandom");
|
||||
|
||||
devfs_root
|
||||
.add("shm", Arc::new(RandomINode::new(true)))
|
||||
.expect("failed to mknod /dev/shm");
|
||||
if let Some(display) = drivers::all_display().first() {
|
||||
use devfs::{EventDev, FbDev, MiceDev};
|
||||
|
||||
|
|
|
@ -249,7 +249,6 @@ impl LinuxProcess {
|
|||
.futexes
|
||||
.entry(uaddr)
|
||||
.or_insert_with(|| {
|
||||
// FIXME: check address
|
||||
let value = unsafe { &*(uaddr as *const AtomicI32) };
|
||||
Futex::new(value)
|
||||
})
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::signal::Signal;
|
||||
use _core::convert::TryFrom;
|
||||
use bitflags::*;
|
||||
|
||||
pub const SIG_ERR: usize = usize::max_value() - 1;
|
||||
|
@ -14,9 +15,15 @@ pub const SIG_IGN: usize = 1;
|
|||
pub struct Sigset(u64);
|
||||
|
||||
impl Sigset {
|
||||
pub fn new(val: u64) -> Self {
|
||||
Sigset(val)
|
||||
}
|
||||
pub fn empty() -> Self {
|
||||
Sigset(0)
|
||||
}
|
||||
pub fn val(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
pub fn contains(&self, sig: Signal) -> bool {
|
||||
(self.0 >> sig as u64 & 1) != 0
|
||||
}
|
||||
|
@ -32,6 +39,24 @@ impl Sigset {
|
|||
pub fn remove_set(&mut self, sigset: &Sigset) {
|
||||
self.0 ^= self.0 & sigset.0;
|
||||
}
|
||||
pub fn mask_with(&self, mask: &Sigset) -> Sigset {
|
||||
Sigset(self.0 & (!mask.0))
|
||||
}
|
||||
pub fn find_first_not_mask_signal(&self, mask: &Sigset) -> Option<Signal> {
|
||||
let masked_signals = self.0 & (!mask.0);
|
||||
for i in 1..65 {
|
||||
if ((masked_signals >> i) & 1) != 0 {
|
||||
return Some(Signal::try_from(i).unwrap());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0 == 0
|
||||
}
|
||||
pub fn is_not_empty(&self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Linux struct sigaction
|
||||
|
|
|
@ -7,114 +7,185 @@ mod action;
|
|||
|
||||
pub use self::action::*;
|
||||
|
||||
/// struct mcontext
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
// gregs
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rdi: usize,
|
||||
pub rsi: usize,
|
||||
pub rbp: usize,
|
||||
pub rbx: usize,
|
||||
pub rdx: usize,
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rsp: usize,
|
||||
pub rip: usize,
|
||||
pub eflags: usize,
|
||||
pub cs: u16,
|
||||
pub gs: u16,
|
||||
pub fs: u16,
|
||||
pub _pad: u16,
|
||||
pub err: usize,
|
||||
pub trapno: usize,
|
||||
pub oldmask: usize,
|
||||
pub cr2: usize,
|
||||
// fpregs
|
||||
// TODO
|
||||
pub fpstate: usize,
|
||||
// reserved
|
||||
pub _reserved1: [usize; 8],
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")] {
|
||||
/// struct mcontext
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MachineContext {
|
||||
// gregs
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rdi: usize,
|
||||
pub rsi: usize,
|
||||
pub rbp: usize,
|
||||
pub rbx: usize,
|
||||
pub rdx: usize,
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rsp: usize,
|
||||
pub rip: usize,
|
||||
pub eflags: usize,
|
||||
pub cs: u16,
|
||||
pub gs: u16,
|
||||
pub fs: u16,
|
||||
pub _pad: u16,
|
||||
pub err: usize,
|
||||
pub trapno: usize,
|
||||
pub oldmask: usize,
|
||||
pub cr2: usize,
|
||||
// fpregs
|
||||
// TODO
|
||||
pub fpstate: usize,
|
||||
// reserved
|
||||
pub _reserved1: [usize; 8],
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn set_pc(&mut self, pc: usize) {
|
||||
self.rip = pc;
|
||||
}
|
||||
pub fn get_pc(&self) -> usize {
|
||||
self.rip
|
||||
}
|
||||
}
|
||||
} else if #[cfg(target_arch = "riscv64")] {
|
||||
/// struct mcontext
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
// TODO
|
||||
pub reserved_: [usize; 16],
|
||||
// pc
|
||||
pub pc: usize,
|
||||
// TODO
|
||||
pub reserved: [usize; 17],
|
||||
// fpregs
|
||||
pub fpstate: [usize; 66],
|
||||
}
|
||||
|
||||
impl Default for MachineContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved_: [0; 16],
|
||||
pc: 0,
|
||||
reserved: [0; 17],
|
||||
fpstate: [0; 66]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn set_pc(&mut self, pc: usize) {
|
||||
self.pc = pc;
|
||||
}
|
||||
pub fn get_pc(&self) -> usize {
|
||||
self.pc
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/// TODO: other archs
|
||||
/// struct mcontext
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MachineContext {
|
||||
// TODO
|
||||
pub reserved_: [usize; 36],
|
||||
}
|
||||
|
||||
impl Default for MachineContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
reserved_: [0; 36],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineContext {
|
||||
pub fn set_pc(&mut self, _pc: usize) {}
|
||||
pub fn get_pc(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum Signal {
|
||||
SIGHUP = 1,
|
||||
SIGINT = 2,
|
||||
SIGQUIT = 3,
|
||||
SIGILL = 4,
|
||||
SIGTRAP = 5,
|
||||
SIGABRT = 6,
|
||||
SIGBUS = 7,
|
||||
SIGFPE = 8,
|
||||
SIGKILL = 9,
|
||||
SIGUSR1 = 10,
|
||||
SIGSEGV = 11,
|
||||
SIGUSR2 = 12,
|
||||
SIGPIPE = 13,
|
||||
SIGALRM = 14,
|
||||
SIGTERM = 15,
|
||||
SIGSTKFLT = 16,
|
||||
SIGCHLD = 17,
|
||||
SIGCONT = 18,
|
||||
SIGSTOP = 19,
|
||||
SIGTSTP = 20,
|
||||
SIGTTIN = 21,
|
||||
SIGTTOU = 22,
|
||||
SIGURG = 23,
|
||||
SIGXCPU = 24,
|
||||
SIGXFSZ = 25,
|
||||
SIGVTALRM = 26,
|
||||
SIGPROF = 27,
|
||||
SIGWINCH = 28,
|
||||
SIGIO = 29,
|
||||
SIGPWR = 30,
|
||||
SIGSYS = 31,
|
||||
// real time signals
|
||||
SIGRT32 = 32,
|
||||
SIGRT33 = 33,
|
||||
SIGRT34 = 34,
|
||||
SIGRT35 = 35,
|
||||
SIGRT36 = 36,
|
||||
SIGRT37 = 37,
|
||||
SIGRT38 = 38,
|
||||
SIGRT39 = 39,
|
||||
SIGRT40 = 40,
|
||||
SIGRT41 = 41,
|
||||
SIGRT42 = 42,
|
||||
SIGRT43 = 43,
|
||||
SIGRT44 = 44,
|
||||
SIGRT45 = 45,
|
||||
SIGRT46 = 46,
|
||||
SIGRT47 = 47,
|
||||
SIGRT48 = 48,
|
||||
SIGRT49 = 49,
|
||||
SIGRT50 = 50,
|
||||
SIGRT51 = 51,
|
||||
SIGRT52 = 52,
|
||||
SIGRT53 = 53,
|
||||
SIGRT54 = 54,
|
||||
SIGRT55 = 55,
|
||||
SIGRT56 = 56,
|
||||
SIGRT57 = 57,
|
||||
SIGRT58 = 58,
|
||||
SIGRT59 = 59,
|
||||
SIGRT60 = 60,
|
||||
SIGRT61 = 61,
|
||||
SIGRT62 = 62,
|
||||
SIGRT63 = 63,
|
||||
SIGRT64 = 64,
|
||||
}
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum Signal {
|
||||
SIGHUP = 1,
|
||||
SIGINT = 2,
|
||||
SIGQUIT = 3,
|
||||
SIGILL = 4,
|
||||
SIGTRAP = 5,
|
||||
SIGABRT = 6,
|
||||
SIGBUS = 7,
|
||||
SIGFPE = 8,
|
||||
SIGKILL = 9,
|
||||
SIGUSR1 = 10,
|
||||
SIGSEGV = 11,
|
||||
SIGUSR2 = 12,
|
||||
SIGPIPE = 13,
|
||||
SIGALRM = 14,
|
||||
SIGTERM = 15,
|
||||
SIGSTKFLT = 16,
|
||||
SIGCHLD = 17,
|
||||
SIGCONT = 18,
|
||||
SIGSTOP = 19,
|
||||
SIGTSTP = 20,
|
||||
SIGTTIN = 21,
|
||||
SIGTTOU = 22,
|
||||
SIGURG = 23,
|
||||
SIGXCPU = 24,
|
||||
SIGXFSZ = 25,
|
||||
SIGVTALRM = 26,
|
||||
SIGPROF = 27,
|
||||
SIGWINCH = 28,
|
||||
SIGIO = 29,
|
||||
SIGPWR = 30,
|
||||
SIGSYS = 31,
|
||||
// real time signals
|
||||
SIGRT32 = 32,
|
||||
SIGRT33 = 33,
|
||||
SIGRT34 = 34,
|
||||
SIGRT35 = 35,
|
||||
SIGRT36 = 36,
|
||||
SIGRT37 = 37,
|
||||
SIGRT38 = 38,
|
||||
SIGRT39 = 39,
|
||||
SIGRT40 = 40,
|
||||
SIGRT41 = 41,
|
||||
SIGRT42 = 42,
|
||||
SIGRT43 = 43,
|
||||
SIGRT44 = 44,
|
||||
SIGRT45 = 45,
|
||||
SIGRT46 = 46,
|
||||
SIGRT47 = 47,
|
||||
SIGRT48 = 48,
|
||||
SIGRT49 = 49,
|
||||
SIGRT50 = 50,
|
||||
SIGRT51 = 51,
|
||||
SIGRT52 = 52,
|
||||
SIGRT53 = 53,
|
||||
SIGRT54 = 54,
|
||||
SIGRT55 = 55,
|
||||
SIGRT56 = 56,
|
||||
SIGRT57 = 57,
|
||||
SIGRT58 = 58,
|
||||
SIGRT59 = 59,
|
||||
SIGRT60 = 60,
|
||||
SIGRT61 = 61,
|
||||
SIGRT62 = 62,
|
||||
SIGRT63 = 63,
|
||||
SIGRT64 = 64,
|
||||
}
|
||||
}
|
||||
|
||||
impl Signal {
|
||||
|
@ -130,13 +201,13 @@ impl Signal {
|
|||
///
|
||||
/// Not exactly the same for now
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct SignalUserContext {
|
||||
pub flags: usize,
|
||||
pub link: usize,
|
||||
pub stack: SignalStack,
|
||||
pub context: MachineContext,
|
||||
pub sig_mask: Sigset,
|
||||
pub context: MachineContext,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
//! Linux Thread
|
||||
|
||||
use crate::error::SysResult;
|
||||
use crate::process::ProcessExt;
|
||||
use crate::signal::{SignalStack, Sigset};
|
||||
use crate::signal::{Signal, SignalStack, SignalUserContext, Sigset};
|
||||
use alloc::sync::Arc;
|
||||
use kernel_hal::user::{Out, UserOutPtr, UserPtr};
|
||||
use kernel_hal::context::{UserContext, UserContextField};
|
||||
use kernel_hal::user::{Out, UserInPtr, UserOutPtr, UserPtr};
|
||||
use spin::{Mutex, MutexGuard};
|
||||
use zircon_object::task::{CurrentThread, Process, Thread};
|
||||
use zircon_object::ZxResult;
|
||||
|
@ -16,6 +18,14 @@ pub trait ThreadExt {
|
|||
fn lock_linux(&self) -> MutexGuard<'_, LinuxThread>;
|
||||
/// Set pointer to thread ID.
|
||||
fn set_tid_address(&self, tidptr: UserOutPtr<i32>);
|
||||
/// Get robust list.
|
||||
fn get_robust_list(
|
||||
&self,
|
||||
_head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
_len_ptr: UserOutPtr<usize>,
|
||||
) -> SysResult;
|
||||
/// Set robust list.
|
||||
fn set_robust_list(&self, head: UserInPtr<RobustList>, len: usize);
|
||||
}
|
||||
|
||||
/// CurrentThread extension for linux
|
||||
|
@ -28,8 +38,12 @@ impl ThreadExt for Thread {
|
|||
fn create_linux(proc: &Arc<Process>) -> ZxResult<Arc<Self>> {
|
||||
let linux_thread = Mutex::new(LinuxThread {
|
||||
clear_child_tid: 0.into(),
|
||||
signals: Sigset::default(),
|
||||
signal_mask: Sigset::default(),
|
||||
signal_alternate_stack: SignalStack::default(),
|
||||
robust_list: 0.into(),
|
||||
robust_list_len: 0,
|
||||
handling_signal: None,
|
||||
});
|
||||
Thread::create_with_ext(proc, "", linux_thread)
|
||||
}
|
||||
|
@ -45,6 +59,21 @@ impl ThreadExt for Thread {
|
|||
fn set_tid_address(&self, tidptr: UserPtr<i32, Out>) {
|
||||
self.lock_linux().clear_child_tid = tidptr;
|
||||
}
|
||||
|
||||
fn get_robust_list(
|
||||
&self,
|
||||
mut _head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
mut _len_ptr: UserOutPtr<usize>,
|
||||
) -> SysResult {
|
||||
_head_ptr = (self.lock_linux().robust_list.as_addr() as *mut RobustList as usize).into();
|
||||
_len_ptr = (&self.lock_linux().robust_list_len as *const usize as usize).into();
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn set_robust_list(&self, head: UserInPtr<RobustList>, len: usize) {
|
||||
self.lock_linux().robust_list = head;
|
||||
self.lock_linux().robust_list_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
impl CurrentThreadExt for CurrentThread {
|
||||
|
@ -65,13 +94,57 @@ impl CurrentThreadExt for CurrentThread {
|
|||
}
|
||||
}
|
||||
|
||||
/// robust_list
|
||||
#[derive(Default)]
|
||||
pub struct RobustList {
|
||||
/// head
|
||||
pub head: usize,
|
||||
/// off
|
||||
pub off: isize,
|
||||
/// pending
|
||||
pub pending: usize,
|
||||
}
|
||||
|
||||
/// Linux specific thread information.
|
||||
pub struct LinuxThread {
|
||||
/// Kernel performs futex wake when thread exits.
|
||||
/// Ref: <http://man7.org/linux/man-pages/man2/set_tid_address.2.html>
|
||||
clear_child_tid: UserOutPtr<i32>,
|
||||
/// Linux signals
|
||||
pub signals: Sigset,
|
||||
/// Signal mask
|
||||
pub signal_mask: Sigset,
|
||||
/// signal alternate stack
|
||||
pub signal_alternate_stack: SignalStack,
|
||||
/// robust_list
|
||||
robust_list: UserInPtr<RobustList>,
|
||||
robust_list_len: usize,
|
||||
/// handling signals
|
||||
pub handling_signal: Option<u32>,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
impl LinuxThread {
|
||||
/// Restore the information after the signal handler returns
|
||||
pub fn restore_after_handle_signal(&mut self, ctx: &mut UserContext, old_ctx: &UserContext) {
|
||||
let ctx_in_us;
|
||||
unsafe {
|
||||
let stack_top = ctx.get_field(UserContextField::StackPointer) as *mut SignalUserContext;
|
||||
ctx_in_us = &*stack_top;
|
||||
}
|
||||
*ctx = *old_ctx;
|
||||
ctx.set_field(UserContextField::InstrPointer, ctx_in_us.context.get_pc());
|
||||
let mut new_mask = Sigset::empty();
|
||||
warn!(
|
||||
"FIXME: the signal mask is not correctly restored, because of align issues of the SignalUserContext with C musl library."
|
||||
);
|
||||
new_mask.insert(Signal::SIGRT33);
|
||||
self.signal_mask = new_mask;
|
||||
self.handling_signal = None;
|
||||
}
|
||||
|
||||
/// Get signal info
|
||||
pub fn get_signal_info(&self) -> (Sigset, Sigset, Option<u32>) {
|
||||
(self.signals, self.signal_mask, self.handling_signal)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,13 @@ rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "1a3246b" }
|
|||
lazy_static = { version = "1.4", features = ["spin_no_std"] }
|
||||
bitvec = { version = "0.22", default-features = false, features = ["alloc"] }
|
||||
lock = { git = "https://github.com/DeathWish5/kernel-sync" }
|
||||
futures = { version = "0.3", default-features = false, features = ["alloc", "async-await"] }
|
||||
|
||||
[dev-dependencies]
|
||||
async-std = { version = "1.10", features = ["unstable"] }
|
||||
|
||||
# LibOS mode
|
||||
[target.'cfg(not(target_os = "none"))'.dependencies]
|
||||
|
||||
# Bare-metal mode
|
||||
[target.'cfg(target_os = "none")'.dependencies]
|
||||
[target.'cfg(target_os = "none")'.dependencies]
|
|
@ -169,6 +169,12 @@ impl Syscall<'_> {
|
|||
/// The unlinkat() system call operates in exactly the same way as either unlink or rmdir.
|
||||
pub fn sys_unlinkat(&self, dirfd: FileDesc, path: UserInPtr<u8>, flags: usize) -> SysResult {
|
||||
let path = path.as_c_str()?;
|
||||
// hard code special path
|
||||
let path = if path == "/dev/shm/testshm" {
|
||||
"/testshm"
|
||||
} else {
|
||||
path
|
||||
};
|
||||
let flags = AtFlags::from_bits_truncate(flags);
|
||||
info!(
|
||||
"unlinkat: dirfd={:?}, path={:?}, flags={:?}",
|
||||
|
|
|
@ -24,6 +24,12 @@ impl Syscall<'_> {
|
|||
) -> SysResult {
|
||||
let proc = self.linux_process();
|
||||
let path = path.as_c_str()?;
|
||||
// hard code special path
|
||||
let path = if path == "/dev/shm/testshm" {
|
||||
"/testshm"
|
||||
} else {
|
||||
path
|
||||
};
|
||||
let flags = OpenFlags::from_bits_truncate(flags);
|
||||
info!(
|
||||
"openat: dir_fd={:?}, path={:?}, flags={:?}, mode={:#o}",
|
||||
|
@ -49,7 +55,6 @@ impl Syscall<'_> {
|
|||
} else {
|
||||
proc.lookup_inode_at(dir_fd, path, true)?
|
||||
};
|
||||
|
||||
let file = File::new(inode, flags, path.into());
|
||||
let fd = proc.add_file(file)?;
|
||||
Ok(fd.into())
|
||||
|
|
|
@ -311,12 +311,12 @@ impl Syscall<'_> {
|
|||
self.into_out_userptr(a2).unwrap(),
|
||||
a3,
|
||||
),
|
||||
// Sys::RT_SIGRETURN => self.sys_rt_sigreturn(),
|
||||
Sys::RT_SIGRETURN => self.sys_rt_sigreturn(),
|
||||
Sys::SIGALTSTACK => self.sys_sigaltstack(
|
||||
self.into_in_userptr(a0).unwrap(),
|
||||
self.into_out_userptr(a1).unwrap(),
|
||||
),
|
||||
// Sys::KILL => self.sys_kill(a0, a1),
|
||||
Sys::KILL => self.sys_kill(a0 as isize, a1),
|
||||
|
||||
// schedule
|
||||
Sys::SCHED_YIELD => self.unimplemented("yield", Ok(0)),
|
||||
|
@ -371,17 +371,6 @@ impl Syscall<'_> {
|
|||
}
|
||||
|
||||
// process
|
||||
Sys::CLONE => {
|
||||
// warn!("a2={} a3={}", a2, a3);
|
||||
// self.sys_clone(
|
||||
// a0,
|
||||
// a1,
|
||||
// self.into_out_userptr(a2).unwrap(),
|
||||
// self.into_out_userptr(a3).unwrap(),
|
||||
// a4,
|
||||
// )
|
||||
self.sys_clone(a0, a1, a2.into(), a3.into(), a4)
|
||||
}
|
||||
Sys::EXECVE => self.sys_execve(
|
||||
self.into_in_userptr(a0).unwrap(),
|
||||
self.into_in_userptr(a1).unwrap(),
|
||||
|
@ -394,11 +383,17 @@ impl Syscall<'_> {
|
|||
.await
|
||||
}
|
||||
Sys::SET_TID_ADDRESS => self.sys_set_tid_address(self.into_out_userptr(a0).unwrap()),
|
||||
Sys::FUTEX => {
|
||||
// ignore timeout argument when op is wake
|
||||
self.sys_futex(a0, a1 as _, a2 as _, a3).await
|
||||
Sys::FUTEX => self.sys_futex(a0, a1 as _, a2 as _, a3, a4, a5 as _).await,
|
||||
Sys::GET_ROBUST_LIST => self.sys_get_robust_list(
|
||||
a0 as _,
|
||||
self.into_out_userptr(a1).unwrap(),
|
||||
self.into_out_userptr(a2).unwrap(),
|
||||
),
|
||||
Sys::SET_ROBUST_LIST => {
|
||||
self.sys_set_robust_list(self.into_in_userptr(a0).unwrap(), a1 as _)
|
||||
}
|
||||
Sys::TKILL => self.unimplemented("tkill", Ok(0)),
|
||||
Sys::TKILL => self.sys_tkill(a0, a1),
|
||||
Sys::TGKILL => self.sys_tgkill(a0, a1, a2),
|
||||
|
||||
// time
|
||||
Sys::NANOSLEEP => self.sys_nanosleep(self.into_in_userptr(a0).unwrap()).await,
|
||||
|
@ -548,6 +543,7 @@ impl Syscall<'_> {
|
|||
Sys::CHOWN => self.unimplemented("chown", Ok(0)),
|
||||
Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1),
|
||||
Sys::TIME => self.sys_time(self.into_out_userptr(a0).unwrap()),
|
||||
Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a4, a3.into()),
|
||||
// Sys::EPOLL_CREATE => self.sys_epoll_create(a0),
|
||||
// Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3),
|
||||
_ => self.unknown_syscall(sys_type),
|
||||
|
@ -556,10 +552,10 @@ impl Syscall<'_> {
|
|||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
async fn riscv64_syscall(&mut self, sys_type: Sys, args: [usize; 6]) -> SysResult {
|
||||
debug!("riscv64_syscall: {:?}, {:?}", sys_type, args);
|
||||
//let [a0, a1, a2, a3, a4, _a5] = args;
|
||||
let [a0, a1, a2, a3, a4, _a5] = args;
|
||||
match sys_type {
|
||||
//Sys::OPEN => self.sys_open(a0.into(), a1, a2),
|
||||
Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a3, a4.into()),
|
||||
_ => self.unknown_syscall(sys_type),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use super::*;
|
||||
use bitflags::bitflags;
|
||||
use core::time::Duration;
|
||||
use futures::pin_mut;
|
||||
use kernel_hal::timer::timer_now;
|
||||
use linux_object::time::*;
|
||||
use zircon_object::task::ThreadState;
|
||||
|
||||
impl Syscall<'_> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -67,16 +71,32 @@ impl Syscall<'_> {
|
|||
/// - `uaddr` - points to the futex word.
|
||||
/// - `op` - the operation to perform on the futex
|
||||
/// - `val` - a value whose meaning and purpose depends on op
|
||||
/// - `timeout` - not support now
|
||||
/// TODO: support timeout
|
||||
/// - `timeout_addr` - provides a timeout for the attempt or acts as val2 when op is REQUEUE
|
||||
/// - `uaddr2` - when op is REQUEUE, points to the target futex
|
||||
/// - `_val3` - is not used
|
||||
pub async fn sys_futex(
|
||||
&self,
|
||||
uaddr: usize,
|
||||
op: u32,
|
||||
val: i32,
|
||||
val: u32,
|
||||
timeout_addr: usize,
|
||||
uaddr2: usize,
|
||||
_val3: u32,
|
||||
) -> SysResult {
|
||||
if self.into_inout_userptr::<i32>(uaddr).is_err() {
|
||||
return Err(LxError::EINVAL);
|
||||
}
|
||||
let op = FutexFlags::from_bits_truncate(op);
|
||||
if !op.contains(FutexFlags::PRIVATE) {
|
||||
warn!("process-shared futex is unimplemented");
|
||||
}
|
||||
let mut val2 = 0;
|
||||
if op.contains(FutexFlags::REQUEUE) {
|
||||
if self.into_inout_userptr::<i32>(uaddr2).is_err() {
|
||||
return Err(LxError::EINVAL);
|
||||
}
|
||||
val2 = timeout_addr;
|
||||
}
|
||||
let timeout = if op.contains(FutexFlags::WAKE) {
|
||||
self.into_inout_userptr::<TimeSpec>(0).unwrap()
|
||||
} else {
|
||||
|
@ -86,32 +106,69 @@ impl Syscall<'_> {
|
|||
Err(_e) => return Err(LxError::EACCES),
|
||||
}
|
||||
};
|
||||
info!(
|
||||
"futex: uaddr: {:#x}, op: {:?}, val: {}, timeout_ptr: {:?}",
|
||||
uaddr, op, val, timeout
|
||||
warn!(
|
||||
"Futex uaddr: {:#x}, op: {:x}, val: {}, timeout_ptr: {:x?}, val2: {}",
|
||||
uaddr,
|
||||
op.bits(),
|
||||
val,
|
||||
timeout,
|
||||
val2,
|
||||
);
|
||||
|
||||
if op.contains(FutexFlags::PRIVATE) {
|
||||
warn!("process-shared futex is unimplemented");
|
||||
}
|
||||
let futex = self.linux_process().get_futex(uaddr);
|
||||
match op.bits & 0xf {
|
||||
0 => {
|
||||
// FIXME: support timeout
|
||||
let _timeout = timeout.read_if_not_null()?;
|
||||
match futex.wait(val).await {
|
||||
let op = op - FutexFlags::PRIVATE;
|
||||
match op {
|
||||
FutexFlags::WAIT => {
|
||||
let timeout = timeout.read_if_not_null()?;
|
||||
let duration: Duration = match timeout {
|
||||
Some(t) => t.into(),
|
||||
None => Duration::from_secs(0),
|
||||
};
|
||||
let into_lxerror = |e: ZxError| match e {
|
||||
ZxError::BAD_STATE => LxError::EAGAIN,
|
||||
e => e.into(),
|
||||
};
|
||||
let future = futex.wait(val as _);
|
||||
let res = if duration.as_millis() == 0 {
|
||||
future.await
|
||||
} else {
|
||||
pin_mut!(future);
|
||||
self.thread
|
||||
.blocking_run(
|
||||
future,
|
||||
ThreadState::BlockedFutex,
|
||||
timer_now() + duration,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
};
|
||||
match res {
|
||||
Ok(_) => Ok(0),
|
||||
Err(ZxError::BAD_STATE) => Err(LxError::EAGAIN),
|
||||
Err(e) => Err(e.into()),
|
||||
Err(e) => Err(into_lxerror(e)),
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
FutexFlags::WAKE => {
|
||||
let woken_up_count = futex.wake(val as usize);
|
||||
Ok(woken_up_count)
|
||||
}
|
||||
FutexFlags::LOCK_PI => {
|
||||
warn!("futex LOCK_PI is unimplemented");
|
||||
Ok(0)
|
||||
}
|
||||
FutexFlags::REQUEUE => {
|
||||
let requeue_futex = self.linux_process().get_futex(uaddr2);
|
||||
let into_lxerror = |e: ZxError| match e {
|
||||
ZxError::BAD_STATE => LxError::EAGAIN,
|
||||
e => e.into(),
|
||||
};
|
||||
let res = futex.requeue(0, val as usize, val2, &requeue_futex, None, false);
|
||||
match res {
|
||||
Ok(_) => Ok(0),
|
||||
Err(e) => Err(into_lxerror(e)),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!("unsupported futex operation: {:?}", op);
|
||||
Err(LxError::ENOSYS)
|
||||
Err(LxError::ENOPROTOOPT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,6 +236,12 @@ bitflags! {
|
|||
const WAIT = 0;
|
||||
/// wakes at most val of the waiters that are waiting on the futex word at the address uaddr.
|
||||
const WAKE = 1;
|
||||
/// wakes up a maximum of val waiters that are waiting on the futex at uaddr. If there are more than val waiters, then the remaining waiters are removed from the wait queue of the source futex at uaddr and added to the wait queue of the target futex at uaddr2. The val2 argument specifies an upper limit on the number of waiters that are requeued to the futex at uaddr2.
|
||||
const REQUEUE = 3;
|
||||
/// (unsupported) is used after an attempt to acquire the lock via an atomic user-mode instruction failed.
|
||||
const LOCK_PI = 6;
|
||||
/// (unsupported) is called when the user-space value at uaddr cannot be changed atomically from a TID (of the owner) to 0.
|
||||
const UNLOCK_PI = 7;
|
||||
/// can be employed with all futex operations, tells the kernel that the futex is process-private and not shared with another process
|
||||
const PRIVATE = 0x80;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,12 @@ impl Syscall<'_> {
|
|||
) -> SysResult {
|
||||
let signal = Signal::try_from(signum as u8).map_err(|_| LxError::EINVAL)?;
|
||||
info!(
|
||||
"rt_sigaction: signal={:?}, act={:?}, oldact={:?}, sigsetsize={}",
|
||||
signal, act, oldact, sigsetsize
|
||||
"rt_sigaction: signal={:?}, act={:?}, oldact={:?}, sigsetsize={}, thread={}",
|
||||
signal,
|
||||
act,
|
||||
oldact,
|
||||
sigsetsize,
|
||||
self.thread.id()
|
||||
);
|
||||
if sigsetsize != core::mem::size_of::<Sigset>()
|
||||
|| signal == Signal::SIGKILL
|
||||
|
@ -60,8 +64,12 @@ impl Syscall<'_> {
|
|||
}
|
||||
let how = How::try_from(how).map_err(|_| LxError::EINVAL)?;
|
||||
info!(
|
||||
"rt_sigprocmask: how={:?}, set={:?}, oldset={:?}, sigsetsize={}",
|
||||
how, set, oldset, sigsetsize
|
||||
"rt_sigprocmask: how={:?}, set={:?}, oldset={:?}, sigsetsize={}, thread={}",
|
||||
how,
|
||||
set,
|
||||
oldset,
|
||||
sigsetsize,
|
||||
self.thread.id()
|
||||
);
|
||||
if sigsetsize != core::mem::size_of::<Sigset>() {
|
||||
return Err(LxError::EINVAL);
|
||||
|
@ -112,4 +120,145 @@ impl Syscall<'_> {
|
|||
*old_ss = ss;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Send a signal to a process specified by pid
|
||||
/// TODO: support all the arguments
|
||||
pub fn sys_kill(&self, pid: isize, signum: usize) -> SysResult {
|
||||
let signal = Signal::try_from(signum as u8).map_err(|_| LxError::EINVAL)?;
|
||||
info!(
|
||||
"kill: thread {} kill process {} with signal {:?}",
|
||||
self.thread.id(),
|
||||
pid,
|
||||
signal
|
||||
);
|
||||
warn!(
|
||||
"The sys_kill only supports killing a process (SIGKILL) or sending a signal to
|
||||
an arbitrary thread of a process within the same job as the calling thread.
|
||||
As for the latter, the signal will be delivered to an arbitrarily selected thread
|
||||
in the target process that is not blocking the signal."
|
||||
);
|
||||
enum SendTarget {
|
||||
EveryProcessInGroup,
|
||||
EveryProcess,
|
||||
EveryProcessInGroupByPID(KoID),
|
||||
Pid(KoID),
|
||||
}
|
||||
let target = match pid {
|
||||
p if p > 0 => SendTarget::Pid(p as KoID),
|
||||
0 => SendTarget::EveryProcessInGroup,
|
||||
-1 => SendTarget::EveryProcess,
|
||||
p if p < -1 => SendTarget::EveryProcessInGroupByPID((-p) as KoID),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
let parent = self.zircon_process().clone();
|
||||
match target {
|
||||
SendTarget::Pid(pid) => {
|
||||
match parent.job().get_child(pid as u64) {
|
||||
Ok(obj) => {
|
||||
match signal {
|
||||
Signal::SIGKILL => {
|
||||
let current_pid = parent.id();
|
||||
if current_pid == (pid as u64) {
|
||||
// killing myself
|
||||
parent.exit((128 + Signal::SIGKILL as i32) as i64);
|
||||
} else {
|
||||
let process: Arc<Process> = obj.downcast_arc().unwrap();
|
||||
process.exit((128 + Signal::SIGKILL as i32) as i64);
|
||||
}
|
||||
}
|
||||
sig => {
|
||||
let process: Arc<Process> = obj.downcast_arc().unwrap();
|
||||
let tids = process.thread_ids();
|
||||
for tid in tids {
|
||||
let thread = process.get_child(tid).unwrap();
|
||||
let thread: Arc<Thread> = thread.downcast_arc().unwrap();
|
||||
let mut thread_linux = thread.lock_linux();
|
||||
if thread_linux.signal_mask.contains(sig) {
|
||||
continue;
|
||||
} else {
|
||||
thread_linux.signals.insert(signal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(0)
|
||||
}
|
||||
Err(_) => Err(LxError::EINVAL),
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a signal to a thread specified by tid
|
||||
pub fn sys_tkill(&mut self, tid: usize, signum: usize) -> SysResult {
|
||||
let signal = Signal::try_from(signum as u8).map_err(|_| LxError::EINVAL)?;
|
||||
info!(
|
||||
"tkill: thread {} kill thread {} with signal {:?}",
|
||||
self.thread.id(),
|
||||
tid,
|
||||
signum
|
||||
);
|
||||
let parent = self.zircon_process().clone();
|
||||
match parent.get_child(tid as u64) {
|
||||
Ok(obj) => {
|
||||
let thread: Arc<Thread> = obj.downcast_arc().unwrap();
|
||||
let mut thread_linux = thread.lock_linux();
|
||||
thread_linux.signals.insert(signal);
|
||||
drop(thread_linux);
|
||||
Ok(0)
|
||||
}
|
||||
Err(_) => Err(LxError::EINVAL),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a signal to a thread specified by tgid (i.e., process) and pid
|
||||
/// Note: the job of the target process should be the same as the calling thread
|
||||
pub fn sys_tgkill(&mut self, tgid: usize, tid: usize, signum: usize) -> SysResult {
|
||||
let signal = Signal::try_from(signum as u8).map_err(|_| LxError::EINVAL)?;
|
||||
info!(
|
||||
"tkill: thread {} kill thread {} in process {} with signal {:?}",
|
||||
self.thread.id(),
|
||||
tid,
|
||||
tgid,
|
||||
signum
|
||||
);
|
||||
warn!(
|
||||
"The signal will be delivered to the target process that
|
||||
belongs to the same job as the calling thread."
|
||||
);
|
||||
let parent = self.zircon_process().clone();
|
||||
match parent
|
||||
.job()
|
||||
.get_child(tgid as u64)
|
||||
.map(|proc| proc.get_child(tid as u64))
|
||||
{
|
||||
Ok(Ok(obj)) => {
|
||||
let thread: Arc<Thread> = obj.downcast_arc().unwrap();
|
||||
let mut thread_linux = thread.lock_linux();
|
||||
thread_linux.signals.insert(signal);
|
||||
drop(thread_linux);
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(LxError::EINVAL),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return from handling some signal
|
||||
pub fn sys_rt_sigreturn(&mut self) -> SysResult {
|
||||
info!(
|
||||
"sigreturn: thread {} returns from handling the signal",
|
||||
self.thread.id()
|
||||
);
|
||||
let old_ctx = self.thread.fetch_backup_context().unwrap();
|
||||
self.thread
|
||||
.with_context(|ctx| {
|
||||
self.thread
|
||||
.lock_linux()
|
||||
.restore_after_handle_signal(ctx, &old_ctx)
|
||||
})
|
||||
.unwrap();
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use super::*;
|
||||
use core::fmt::Debug;
|
||||
use core::mem::size_of;
|
||||
|
||||
use alloc::string::ToString;
|
||||
use bitflags::bitflags;
|
||||
|
||||
use kernel_hal::context::UserContextField;
|
||||
use linux_object::thread::{CurrentThreadExt, ThreadExt};
|
||||
// use linux_object::time::TimeSpec;
|
||||
use linux_object::thread::{CurrentThreadExt, RobustList, ThreadExt};
|
||||
use linux_object::{fs::INodeExt, loader::LinuxElfLoader};
|
||||
|
||||
/// Syscalls for process.
|
||||
|
@ -109,8 +109,8 @@ impl Syscall<'_> {
|
|||
flags: usize,
|
||||
newsp: usize,
|
||||
mut parent_tid: UserOutPtr<i32>,
|
||||
mut child_tid: UserOutPtr<i32>,
|
||||
newtls: usize,
|
||||
mut child_tid: UserOutPtr<i32>,
|
||||
) -> SysResult {
|
||||
let _flags = CloneFlags::from_bits_truncate(flags);
|
||||
info!(
|
||||
|
@ -294,7 +294,7 @@ impl Syscall<'_> {
|
|||
// self.zircon_process().signal_set(Signal::SIGNALED);
|
||||
// Workaround, the child process could NOT exit correctly
|
||||
self.thread
|
||||
.with_context(|ctx| ctx.setup_uspace(entry, sp, 0, 0))?;
|
||||
.with_context(|ctx| ctx.setup_uspace(entry, sp, &[0, 0, 0]))?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -303,28 +303,6 @@ impl Syscall<'_> {
|
|||
// Ok(0)
|
||||
// }
|
||||
//
|
||||
// /// Kill the process
|
||||
// pub fn sys_kill(&self, pid: usize, sig: usize) -> SysResult {
|
||||
// info!(
|
||||
// "kill: thread {} kill process {} with signal {}",
|
||||
// thread::current().id(),
|
||||
// pid,
|
||||
// sig
|
||||
// );
|
||||
// let current_pid = self.process().pid.get().clone();
|
||||
// if current_pid == pid {
|
||||
// // killing myself
|
||||
// self.sys_exit_group(sig);
|
||||
// } else {
|
||||
// if let Some(proc_arc) = PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade()) {
|
||||
// let mut proc = proc_arc.lock();
|
||||
// proc.exit(sig);
|
||||
// Ok(0)
|
||||
// } else {
|
||||
// Err(LxError::EINVAL)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// `sys_gettid` returns the caller's thread ID (TID)
|
||||
/// (see [linux man gettid(2)](https://www.man7.org/linux/man-pages/man2/gettid.2.html)).
|
||||
|
@ -415,6 +393,28 @@ impl Syscall<'_> {
|
|||
let tid = self.thread.id();
|
||||
Ok(tid as usize)
|
||||
}
|
||||
|
||||
/// Get robust list.
|
||||
pub fn sys_get_robust_list(
|
||||
&self,
|
||||
pid: i32,
|
||||
head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
len_ptr: UserOutPtr<usize>,
|
||||
) -> SysResult {
|
||||
if pid == 0 {
|
||||
return self.thread.get_robust_list(head_ptr, len_ptr);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Set robust list.
|
||||
pub fn sys_set_robust_list(&self, head: UserInPtr<RobustList>, len: usize) -> SysResult {
|
||||
if len != size_of::<RobustList>() {
|
||||
return Err(LxError::EINVAL);
|
||||
}
|
||||
self.thread.set_robust_list(head, len);
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||
use core::{future::Future, pin::Pin};
|
||||
use linux_object::signal::{
|
||||
SigInfo, SiginfoFields, Signal, SignalActionFlags, SignalUserContext, Sigset,
|
||||
};
|
||||
|
||||
use kernel_hal::context::{TrapReason, UserContext, UserContextField};
|
||||
use linux_object::fs::{vfs::FileSystem, INodeExt};
|
||||
|
@ -59,6 +62,14 @@ async fn run_user(thread: CurrentThread) {
|
|||
break;
|
||||
}
|
||||
|
||||
// check the signal and handle
|
||||
let (signals, sigmask, handling_signal) = thread.inner().lock_linux().get_signal_info();
|
||||
if signals.mask_with(&sigmask).is_not_empty() && handling_signal.is_none() {
|
||||
let signal = signals.find_first_not_mask_signal(&sigmask).unwrap();
|
||||
thread.lock_linux().handling_signal = Some(signal as u32);
|
||||
ctx = handle_signal(&thread, ctx, signal, sigmask).await;
|
||||
}
|
||||
|
||||
// run
|
||||
trace!("go to user: tid = {} ctx = {:#x?}", thread.id(), ctx);
|
||||
kernel_hal::interrupt::intr_off(); // trapframe can't be interrupted
|
||||
|
@ -72,6 +83,66 @@ async fn run_user(thread: CurrentThread) {
|
|||
}
|
||||
}
|
||||
|
||||
async fn handle_signal(
|
||||
thread: &CurrentThread,
|
||||
mut ctx: Box<UserContext>,
|
||||
signal: Signal,
|
||||
sigmask: Sigset,
|
||||
) -> Box<UserContext> {
|
||||
warn!("Not fully implemented SignalInfo, SignalStack, SignalActionFlags except SIGINFO");
|
||||
let action = thread.proc().linux().signal_action(signal);
|
||||
let signal_info = SigInfo {
|
||||
signo: 0,
|
||||
errno: 0,
|
||||
code: linux_object::signal::SignalCode::TKILL,
|
||||
field: SiginfoFields::default(),
|
||||
};
|
||||
let mut signal_context = SignalUserContext {
|
||||
sig_mask: sigmask,
|
||||
..Default::default()
|
||||
};
|
||||
// backup current context and set new context
|
||||
unsafe {
|
||||
thread.backup_context(*ctx);
|
||||
let mut sp = (*ctx).get_field(UserContextField::StackPointer) - 0x200;
|
||||
let mut siginfo_ptr = 0;
|
||||
if action.flags.contains(SignalActionFlags::SIGINFO) {
|
||||
sp &= !0xF;
|
||||
sp = push_stack::<SigInfo>(sp, signal_info);
|
||||
siginfo_ptr = sp;
|
||||
let pc = (*ctx).get_field(UserContextField::InstrPointer);
|
||||
signal_context.context.set_pc(pc);
|
||||
sp &= !0xF;
|
||||
sp = push_stack::<SignalUserContext>(sp, signal_context);
|
||||
}
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")] {
|
||||
sp &= !0xF;
|
||||
sp = push_stack::<usize>(sp, action.restorer);
|
||||
} else {
|
||||
(*ctx).set_ra(action.restorer);
|
||||
}
|
||||
}
|
||||
if action.flags.contains(SignalActionFlags::SIGINFO) {
|
||||
(*ctx).setup_uspace(action.handler, sp, &[signal as usize, siginfo_ptr, sp]);
|
||||
} else {
|
||||
(*ctx).setup_uspace(action.handler, sp, &[signal as usize, 0, 0]);
|
||||
}
|
||||
(*ctx).enter_uspace();
|
||||
}
|
||||
ctx
|
||||
}
|
||||
|
||||
/// Push a object onto stack
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is handling a raw pointer to the top of the stack .
|
||||
pub unsafe fn push_stack<T>(stack_top: usize, val: T) -> usize {
|
||||
let stack_top = (stack_top as *mut T).sub(1);
|
||||
*stack_top = val;
|
||||
stack_top as usize
|
||||
}
|
||||
|
||||
async fn handle_user_trap(thread: &CurrentThread, mut ctx: Box<UserContext>) -> ZxResult {
|
||||
let reason = ctx.trap_reason();
|
||||
if let TrapReason::Syscall = reason {
|
||||
|
|
2
tests
2
tests
|
@ -1 +1 @@
|
|||
Subproject commit 1dbd661aeba09a2c55e1f920e72b226782d3753d
|
||||
Subproject commit 84c94a5bd0a0ccdbdcffd57a59e62c819f0769b5
|
|
@ -61,6 +61,8 @@ pub fn boot_options() -> BootOptions {
|
|||
log_level: String::from(*options.get("LOG").unwrap_or(&"")),
|
||||
#[cfg(feature = "linux")]
|
||||
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
|
||||
// root_proc: String::from(*options.get("ROOTPROC")
|
||||
// .unwrap_or(&"/libc-test/functional/pthread_mutex.exe")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ kernel-hal = { path = "../kernel-hal", default-features = false }
|
|||
numeric-enum-macro = "0.2"
|
||||
futures = { version = "0.3", default-features = false, features = ["alloc", "async-await"] }
|
||||
xmas-elf = { version = "0.7", optional = true }
|
||||
region-alloc = { git = "https://github.com/rzswh/region-allocator", rev = "122c7a71" }
|
||||
region-alloc = { git = "https://github.91chi.fun//https://github.com/rzswh/region-allocator", rev = "122c7a71" }
|
||||
lazy_static = { version = "1.4", features = ["spin_no_std" ] }
|
||||
cfg-if = "1.0"
|
||||
#rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! - `hypervisor`: Enables `zircon_object::hypervisor` (`Guest` and `Vcpu`).
|
||||
|
||||
#![no_std]
|
||||
#![deny(warnings, unsafe_code, unused_must_use, missing_docs)]
|
||||
// #![deny(warnings, unsafe_code, unused_must_use, missing_docs)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
|
||||
|
|
|
@ -222,11 +222,14 @@ impl Futex {
|
|||
requeue_count: usize,
|
||||
requeue_futex: &Arc<Futex>,
|
||||
new_requeue_owner: Option<Arc<Thread>>,
|
||||
check_value: bool,
|
||||
) -> ZxResult {
|
||||
let mut inner = self.inner.lock();
|
||||
// check value
|
||||
if self.value.load(Ordering::SeqCst) != current_value {
|
||||
return Err(ZxError::BAD_STATE);
|
||||
if check_value {
|
||||
// check value
|
||||
if self.value.load(Ordering::SeqCst) != current_value {
|
||||
return Err(ZxError::BAD_STATE);
|
||||
}
|
||||
}
|
||||
// wake
|
||||
for _ in 0..wake_count {
|
||||
|
@ -364,10 +367,10 @@ mod tests {
|
|||
|
||||
// inconsistent value should fail.
|
||||
assert_eq!(
|
||||
futex.requeue(1, 1, 1, &requeue_futex, None),
|
||||
futex.requeue(1, 1, 1, &requeue_futex, None, true),
|
||||
Err(ZxError::BAD_STATE)
|
||||
);
|
||||
assert!(futex.requeue(2, 1, 1, &requeue_futex, None).is_ok());
|
||||
assert!(futex.requeue(2, 1, 1, &requeue_futex, None, true).is_ok());
|
||||
// 1 waiter waken, 1 waiter moved into `requeue_futex`.
|
||||
assert_eq!(futex.inner.lock().waiter_queue.len(), 0);
|
||||
assert_eq!(requeue_futex.inner.lock().waiter_queue.len(), 1);
|
||||
|
|
|
@ -104,6 +104,11 @@ struct ThreadInner {
|
|||
/// It will be taken away when running this thread.
|
||||
context: Option<Box<UserContext>>,
|
||||
|
||||
/// Thread context before handling the signal
|
||||
///
|
||||
/// It only works when executing signal handlers
|
||||
context_before: Option<UserContext>,
|
||||
|
||||
/// The number of existing `SuspendToken`.
|
||||
suspend_count: usize,
|
||||
/// The waker of task when suspending.
|
||||
|
@ -162,6 +167,11 @@ impl ThreadInner {
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Backup current context
|
||||
fn backup_context(&mut self, context: UserContext) {
|
||||
self.context_before = Some(context);
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -233,7 +243,7 @@ impl Thread {
|
|||
/// Returns a copy of saved context of current thread, or `Err(ZxError::BAD_STATE)`
|
||||
/// if the thread is running.
|
||||
pub fn context_cloned(&self) -> ZxResult<UserContext> {
|
||||
self.with_context(|ctx| ctx.clone())
|
||||
self.with_context(|ctx| *ctx)
|
||||
}
|
||||
|
||||
/// Access saved context of current thread, or `Err(ZxError::BAD_STATE)` if
|
||||
|
@ -250,6 +260,18 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
/// Backup current user context before calling signal handler
|
||||
pub fn backup_context(&self, context: UserContext) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.backup_context(context);
|
||||
}
|
||||
|
||||
/// Fetch the context backup
|
||||
pub fn fetch_backup_context(&self) -> Option<UserContext> {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.context_before.take()
|
||||
}
|
||||
|
||||
/// Start execution on the thread.
|
||||
pub fn start(self: &Arc<Self>, thread_fn: ThreadFn) -> ZxResult {
|
||||
self.inner
|
||||
|
@ -270,7 +292,7 @@ impl Thread {
|
|||
arg2: usize,
|
||||
thread_fn: ThreadFn,
|
||||
) -> ZxResult {
|
||||
self.with_context(|ctx| ctx.setup_uspace(entry, stack, arg1, arg2))?;
|
||||
self.with_context(|ctx| ctx.setup_uspace(entry, stack, &[arg1, arg2, 0]))?;
|
||||
self.start(thread_fn)
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ impl Syscall<'_> {
|
|||
requeue_count as usize,
|
||||
&requeue_futex,
|
||||
new_requeue_owner,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue