Jump to trampoline after SYS_{READ,WRITE} EINTR.
This commit is contained in:
@@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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?
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user