Jump to trampoline after SYS_{READ,WRITE} EINTR.

This commit is contained in:
4lDO2
2024-06-29 15:58:09 +02:00
parent a166a1ebb2
commit 5460ffc4c9
6 changed files with 77 additions and 12 deletions
+20 -1
View File
@@ -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),
);
}
+1
View File
@@ -36,6 +36,7 @@ pub mod auxv_defs;
pub mod signal;
pub mod sync;
pub mod sys;
pub mod thread;
pub type Tcb = GenericTcb<RtSigarea>;
+13 -6
View File
@@ -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<impl FnMut(u32, bool) -> 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?
+35
View File
@@ -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<usize> {
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<usize> {
loop {
let res = syscall::write(fd, buf);
if res == Err(Error::new(EINTR)) {
unsafe {
manually_enter_trampoline();
}
}
return res;
}
}
+3 -2
View File
@@ -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 {
+5 -3
View File
@@ -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<ssize_t, Errno> {
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<ssize_t, Errno> {
unsafe {
@@ -1124,7 +1125,8 @@ impl Pal for Sys {
}
fn write(fd: c_int, buf: &[u8]) -> Result<ssize_t, Errno> {
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<ssize_t, Errno> {
unsafe {