diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 63b59c9faa..67a3600c65 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -6,8 +6,9 @@ use syscall::error::*; use syscall::flag::*; use crate::proc::{fork_inner, FdGuard}; -use crate::signal::SigStack; +use crate::signal::{tmp_disable_signals, SigStack}; use crate::signal::{inner_c, RtSigarea, PROC_CONTROL_STRUCT}; +use crate::Tcb; // Setup a stack starting from the very end of the address space, and then growing downwards. pub(crate) const STACK_TOP: usize = 1 << 47; @@ -357,3 +358,21 @@ pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) { } static SUPPORTS_XSAVE: AtomicU8 = AtomicU8::new(1); // FIXME + +pub unsafe fn manually_enter_trampoline() { + let _g = tmp_disable_signals(); + + let a = &Tcb::current().unwrap().os_specific.control; + a.saved_archdep_reg.set(0); // TODO: Just reset DF on x86? + + core::arch::asm!(" + lea rax, [rip + 2f] + mov fs:[{tcb_sc_off} + {sc_saved_rip}], rax + jmp __relibc_internal_sigentry + 2: + ", + out("rax") _, + tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control), + sc_saved_rip = const offset_of!(Sigcontrol, saved_ip), + ); +} diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index a1f3189c09..0a864aa87a 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -36,6 +36,7 @@ pub mod auxv_defs; pub mod signal; pub mod sync; +pub mod sys; pub mod thread; pub type Tcb = GenericTcb; diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 0eeaf73581..2cb8da5329 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -73,7 +73,9 @@ unsafe fn inner(stack: &mut SigStack) { }; let handler = match sigaction.kind { - SigactionKind::Ignore => unreachable!(), + SigactionKind::Ignore => { + panic!("ctl {:x?} signal {}", os.control, stack.sig_num) + } SigactionKind::Default => { syscall::exit(stack.sig_num << 8); unreachable!(); @@ -95,8 +97,10 @@ unsafe fn inner(stack: &mut SigStack) { let sig_group = stack.sig_num / 32; - let prev_w0 = os.control.word[0].fetch_add(sigallow_inside_lo.wrapping_sub(prev_sigallow_lo), Ordering::Relaxed); - let prev_w1 = os.control.word[1].fetch_add(sigallow_inside_hi.wrapping_sub(prev_sigallow_hi), Ordering::Relaxed); + //let _ = syscall::write(1, &alloc::format!("WORD0 {:x?}\n", os.control.word).as_bytes()); + let prev_w0 = os.control.word[0].fetch_add((sigallow_inside_lo << 32).wrapping_sub(prev_sigallow_lo << 32), Ordering::Relaxed); + let prev_w1 = os.control.word[1].fetch_add((sigallow_inside_hi << 32).wrapping_sub(prev_sigallow_hi << 32), Ordering::Relaxed); + //let _ = syscall::write(1, &alloc::format!("WORD1 {:x?}\n", os.control.word).as_bytes()); // TODO: If sa_mask caused signals to be unblocked, deliver one or all of those first? @@ -117,8 +121,10 @@ unsafe fn inner(stack: &mut SigStack) { core::sync::atomic::compiler_fence(Ordering::Acquire); // Update allowset again. - let prev_w0 = os.control.word[0].fetch_add(prev_sigallow_lo.wrapping_sub(sigallow_inside_lo), Ordering::Relaxed); - let prev_w1 = os.control.word[1].fetch_add(prev_sigallow_hi.wrapping_sub(sigallow_inside_hi), Ordering::Relaxed); + //let _ = syscall::write(1, &alloc::format!("WORD2 {:x?}\n", os.control.word).as_bytes()); + let prev_w0 = os.control.word[0].fetch_add((prev_sigallow_lo << 32).wrapping_sub(sigallow_inside_lo << 32), Ordering::Relaxed); + let prev_w1 = os.control.word[1].fetch_add((prev_sigallow_hi << 32).wrapping_sub(sigallow_inside_hi << 32), Ordering::Relaxed); + //let _ = syscall::write(1, &alloc::format!("WORD3 {:x?}\n", os.control.word).as_bytes()); // TODO: If resetting the sigmask caused signals to be unblocked, then should they be delivered // here? And would it be possible to tail-call-optimize that? @@ -167,13 +173,14 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option u32 let mut can_raise = 0; let mut cant_raise = 0; + //let _ = syscall::write(1, &alloc::format!("OLDWORD {:x?}\n", ctl.word).as_bytes()); for i in 0..2 { - let pending_bits = words[i] & 0xffff_ffff; let old_allow_bits = words[i] & 0xffff_ffff_0000_0000; let new_allow_bits = u64::from(!op(!((old_allow_bits >> 32) as u32), i == 1)) << 32; ctl.word[i].fetch_add(new_allow_bits.wrapping_sub(old_allow_bits), Ordering::Relaxed); } + //let _ = syscall::write(1, &alloc::format!("NEWWORD {:x?}\n", ctl.word).as_bytes()); // TODO: Prioritize cant_raise realtime signals? diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs new file mode 100644 index 0000000000..e9ec7383a8 --- /dev/null +++ b/redox-rt/src/sys.rs @@ -0,0 +1,35 @@ +use syscall::error::{Result, Error, EINTR}; + +use crate::arch::manually_enter_trampoline; +use crate::signal::tmp_disable_signals; + +// TODO: uninitialized memory? +#[inline] +pub fn posix_read(fd: usize, buf: &mut [u8]) -> Result { + loop { + let res = syscall::read(fd, buf); + + if res == Err(Error::new(EINTR)) { + unsafe { + manually_enter_trampoline(); + } + } + + return res; + } +} +#[inline] +pub fn posix_write(fd: usize, buf: &[u8]) -> Result { + loop { + let res = syscall::write(fd, buf); + + if res == Err(Error::new(EINTR)) { + unsafe { + manually_enter_trampoline(); + } + } + + return res; + + } +} diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 821efb0bb0..7001c07d72 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -1,5 +1,6 @@ use core::{slice, str}; +use redox_rt::sys::{posix_read, posix_write}; use syscall::{Error, Result, WaitFlags, EMFILE}; use crate::{ @@ -147,7 +148,7 @@ pub unsafe extern "C" fn redox_dup2_v1( } #[no_mangle] pub unsafe extern "C" fn redox_read_v1(fd: usize, dst_base: *mut u8, dst_len: usize) -> RawResult { - Error::mux(syscall::read( + Error::mux(posix_read( fd, slice::from_raw_parts_mut(dst_base, dst_len), )) @@ -158,7 +159,7 @@ pub unsafe extern "C" fn redox_write_v1( src_base: *const u8, src_len: usize, ) -> RawResult { - Error::mux(syscall::write(fd, slice::from_raw_parts(src_base, src_len))) + Error::mux(posix_write(fd, slice::from_raw_parts(src_base, src_len))) } #[no_mangle] pub unsafe extern "C" fn redox_fsync_v1(fd: usize) -> RawResult { diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index dae77e6d43..83a5cbbe1b 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -10,7 +10,7 @@ use crate::{ fs::File, header::{ dirent::dirent, - errno::{EBADR, EINVAL, EIO, ENOENT, ENOMEM, ENOSYS, EPERM, ERANGE}, + errno::{EBADF, EBADFD, EBADR, EINVAL, EIO, ENOENT, ENOMEM, ENOSYS, EPERM, ERANGE}, fcntl, limits, sys_mman::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE}, sys_random, @@ -824,7 +824,8 @@ impl Pal for Sys { } fn read(fd: c_int, buf: &mut [u8]) -> Result { - Ok(syscall::read(fd as usize, buf)? as ssize_t) + let fd = usize::try_from(fd).map_err(|_| Errno(EBADF))?; + Ok(redox_rt::sys::posix_read(fd, buf)? as ssize_t) } fn pread(fd: c_int, buf: &mut [u8], offset: off_t) -> Result { unsafe { @@ -1124,7 +1125,8 @@ impl Pal for Sys { } fn write(fd: c_int, buf: &[u8]) -> Result { - Ok(syscall::write(fd as usize, buf)? as ssize_t) + let fd = usize::try_from(fd).map_err(|_| Errno(EBADFD))?; + Ok(redox_rt::sys::posix_write(fd, buf)? as ssize_t) } fn pwrite(fd: c_int, buf: &[u8], offset: off_t) -> Result { unsafe {