Enable syscall restart in futex_wait.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
#![no_std]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::mem::{self, offset_of};
|
||||
use core::{
|
||||
arch::asm,
|
||||
mem::{self, offset_of},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
@@ -109,4 +111,3 @@ impl<T> ExpectTlsFree for Option<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use core::mem::offset_of;
|
||||
|
||||
use syscall::data::*;
|
||||
use syscall::error::*;
|
||||
use syscall::{data::*, error::*};
|
||||
|
||||
use crate::proc::{fork_inner, FdGuard};
|
||||
use crate::signal::SigStack;
|
||||
use crate::signal::{inner_c, RtSigarea, PROC_CONTROL_STRUCT};
|
||||
use crate::Tcb;
|
||||
use crate::{
|
||||
proc::{fork_inner, FdGuard},
|
||||
signal::{inner_c, RtSigarea, SigStack, PROC_CONTROL_STRUCT},
|
||||
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;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use core::mem::offset_of;
|
||||
use core::sync::atomic::Ordering;
|
||||
use core::{mem::offset_of, sync::atomic::Ordering};
|
||||
|
||||
use syscall::*;
|
||||
|
||||
use crate::proc::{fork_inner, FdGuard};
|
||||
use crate::signal::{inner_fastcall, PROC_CONTROL_STRUCT, RtSigarea, SigStack};
|
||||
use crate::{
|
||||
proc::{fork_inner, FdGuard},
|
||||
signal::{inner_fastcall, RtSigarea, SigStack, PROC_CONTROL_STRUCT},
|
||||
};
|
||||
|
||||
// Setup a stack starting from the very end of the address space, and then growing downwards.
|
||||
pub(crate) const STACK_TOP: usize = 1 << 31;
|
||||
@@ -38,8 +39,8 @@ pub struct ArchIntRegs {
|
||||
pub edx: usize, // avail +32
|
||||
|
||||
pub eflags: usize, // avail +36
|
||||
pub eip: usize, // avail +40
|
||||
pub esp: usize, // avail +44
|
||||
pub eip: usize, // avail +40
|
||||
pub esp: usize, // avail +44
|
||||
}
|
||||
|
||||
/// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS
|
||||
@@ -256,7 +257,10 @@ pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) {
|
||||
}
|
||||
pub unsafe fn manually_enter_trampoline() {
|
||||
let c = &crate::Tcb::current().unwrap().os_specific.control;
|
||||
c.control_flags.store(c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
c.control_flags.store(
|
||||
c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
c.saved_archdep_reg.set(0); // TODO: Just reset DF on x86?
|
||||
|
||||
core::arch::asm!("
|
||||
|
||||
+18
-10
@@ -1,14 +1,19 @@
|
||||
use core::mem::offset_of;
|
||||
use core::sync::atomic::{AtomicU8, Ordering};
|
||||
use core::{
|
||||
mem::offset_of,
|
||||
sync::atomic::{AtomicU8, Ordering},
|
||||
};
|
||||
|
||||
use syscall::data::{Sigcontrol, SigProcControl};
|
||||
use syscall::error::*;
|
||||
use syscall::flag::*;
|
||||
use syscall::{
|
||||
data::{SigProcControl, Sigcontrol},
|
||||
error::*,
|
||||
flag::*,
|
||||
};
|
||||
|
||||
use crate::proc::{fork_inner, FdGuard};
|
||||
use crate::signal::{tmp_disable_signals, SigStack};
|
||||
use crate::signal::{inner_c, RtSigarea, PROC_CONTROL_STRUCT};
|
||||
use crate::Tcb;
|
||||
use crate::{
|
||||
proc::{fork_inner, FdGuard},
|
||||
signal::{inner_c, tmp_disable_signals, RtSigarea, SigStack, PROC_CONTROL_STRUCT},
|
||||
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;
|
||||
@@ -378,7 +383,10 @@ static SUPPORTS_AVX: AtomicU8 = AtomicU8::new(1); // FIXME
|
||||
|
||||
pub unsafe fn manually_enter_trampoline() {
|
||||
let c = &Tcb::current().unwrap().os_specific.control;
|
||||
c.control_flags.store(c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
c.control_flags.store(
|
||||
c.control_flags.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
c.saved_archdep_reg.set(0); // TODO: Just reset DF on x86?
|
||||
|
||||
core::arch::asm!("
|
||||
|
||||
+20
-7
@@ -1,5 +1,12 @@
|
||||
#![no_std]
|
||||
#![feature(asm_const, array_chunks, int_roundings, let_chains, slice_ptr_get, sync_unsafe_cell)]
|
||||
#![feature(
|
||||
asm_const,
|
||||
array_chunks,
|
||||
int_roundings,
|
||||
let_chains,
|
||||
slice_ptr_get,
|
||||
sync_unsafe_cell
|
||||
)]
|
||||
#![forbid(unreachable_patterns)]
|
||||
|
||||
use generic_rt::{ExpectTlsFree, GenericTcb};
|
||||
@@ -101,12 +108,18 @@ pub fn initialize_freestanding() {
|
||||
|
||||
// TODO: TLS
|
||||
let page = unsafe {
|
||||
&mut *(syscall::fmap(!0, &syscall::Map {
|
||||
offset: 0,
|
||||
size: syscall::PAGE_SIZE,
|
||||
flags: syscall::MapFlags::PROT_READ | syscall::MapFlags::PROT_WRITE | syscall::MapFlags::MAP_PRIVATE,
|
||||
address: 0,
|
||||
}).unwrap() as *mut Tcb)
|
||||
&mut *(syscall::fmap(
|
||||
!0,
|
||||
&syscall::Map {
|
||||
offset: 0,
|
||||
size: syscall::PAGE_SIZE,
|
||||
flags: syscall::MapFlags::PROT_READ
|
||||
| syscall::MapFlags::PROT_WRITE
|
||||
| syscall::MapFlags::MAP_PRIVATE,
|
||||
address: 0,
|
||||
},
|
||||
)
|
||||
.unwrap() as *mut Tcb)
|
||||
};
|
||||
page.tcb_ptr = page;
|
||||
page.tcb_len = syscall::PAGE_SIZE;
|
||||
|
||||
+26
-16
@@ -1,5 +1,5 @@
|
||||
use core::mem::size_of;
|
||||
use crate::{arch::*, auxv_defs::*};
|
||||
use core::mem::size_of;
|
||||
|
||||
use alloc::{boxed::Box, collections::BTreeMap, vec};
|
||||
|
||||
@@ -267,18 +267,23 @@ where
|
||||
let new_page_no = sp / PAGE_SIZE;
|
||||
let new_page_off = sp % PAGE_SIZE;
|
||||
|
||||
let page = if let Some(ref mut page) = stack_page && old_page_no == new_page_no {
|
||||
let page = if let Some(ref mut page) = stack_page
|
||||
&& old_page_no == new_page_no
|
||||
{
|
||||
page
|
||||
} else if let Some(ref mut stack_page) = stack_page {
|
||||
stack_page.remap(new_page_no * PAGE_SIZE, PROT_WRITE)?;
|
||||
stack_page
|
||||
} else {
|
||||
let new = MmapGuard::map(*grants_fd, &Map {
|
||||
offset: new_page_no * PAGE_SIZE,
|
||||
size: PAGE_SIZE,
|
||||
flags: PROT_WRITE,
|
||||
address: 0, // let kernel decide
|
||||
})?;
|
||||
let new = MmapGuard::map(
|
||||
*grants_fd,
|
||||
&Map {
|
||||
offset: new_page_no * PAGE_SIZE,
|
||||
size: PAGE_SIZE,
|
||||
flags: PROT_WRITE,
|
||||
address: 0, // let kernel decide
|
||||
},
|
||||
)?;
|
||||
|
||||
stack_page.insert(new)
|
||||
};
|
||||
@@ -422,12 +427,15 @@ where
|
||||
push(argc)?;
|
||||
|
||||
if let Ok(sighandler_fd) = syscall::dup(*open_via_dup, b"sighandler").map(FdGuard::new) {
|
||||
let _ = syscall::write(*sighandler_fd, &SetSighandlerData {
|
||||
user_handler: 0,
|
||||
excp_handler: 0,
|
||||
thread_control_addr: 0,
|
||||
proc_control_addr: 0,
|
||||
});
|
||||
let _ = syscall::write(
|
||||
*sighandler_fd,
|
||||
&SetSighandlerData {
|
||||
user_handler: 0,
|
||||
excp_handler: 0,
|
||||
thread_control_addr: 0,
|
||||
proc_control_addr: 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@@ -818,9 +826,11 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
|
||||
// reference to the TCB and whatever pages stores the signal proc control struct.
|
||||
{
|
||||
let new_sighandler_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"sighandler")?);
|
||||
let _ = syscall::write(*new_sighandler_fd, &crate::signal::current_setsighandler_struct())?;
|
||||
let _ = syscall::write(
|
||||
*new_sighandler_fd,
|
||||
&crate::signal::current_setsighandler_struct(),
|
||||
)?;
|
||||
}
|
||||
|
||||
}
|
||||
copy_env_regs(*cur_pid_fd, *new_pid_fd)?;
|
||||
}
|
||||
|
||||
+141
-52
@@ -1,12 +1,17 @@
|
||||
use core::cell::{Cell, UnsafeCell};
|
||||
use core::ffi::c_int;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use core::{
|
||||
cell::{Cell, UnsafeCell},
|
||||
ffi::c_int,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use syscall::{RawAction, ENOMEM, EPERM, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ};
|
||||
use syscall::{Error, Result, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, data::AtomicU64};
|
||||
use syscall::{
|
||||
data::AtomicU64, Error, RawAction, Result, SetSighandlerData, SigProcControl, Sigcontrol,
|
||||
SigcontrolFlags, EINVAL, ENOMEM, EPERM, SIGABRT, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGILL,
|
||||
SIGKILL, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTRAP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG,
|
||||
SIGWINCH, SIGXCPU, SIGXFSZ,
|
||||
};
|
||||
|
||||
use crate::{arch::*, Tcb};
|
||||
use crate::sync::Mutex;
|
||||
use crate::{arch::*, sync::Mutex, Tcb};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static CPUID_EAX1_ECX: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
|
||||
@@ -52,11 +57,15 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
if action.flags.contains(SigactionFlags::RESETHAND) {
|
||||
// TODO: other things that must be set
|
||||
drop(guard);
|
||||
sigaction(stack.sig_num as u8, Some(&Sigaction {
|
||||
kind: SigactionKind::Default,
|
||||
mask: 0,
|
||||
flags: SigactionFlags::empty(),
|
||||
}), None);
|
||||
sigaction(
|
||||
stack.sig_num as u8,
|
||||
Some(&Sigaction {
|
||||
kind: SigactionKind::Default,
|
||||
mask: 0,
|
||||
flags: SigactionFlags::empty(),
|
||||
}),
|
||||
None,
|
||||
);
|
||||
}
|
||||
action
|
||||
};
|
||||
@@ -86,21 +95,36 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
let sigallow_inside_hi = sigallow_inside >> 32;
|
||||
|
||||
//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 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?
|
||||
|
||||
// Re-enable signals again.
|
||||
let control_flags = &os.control.control_flags;
|
||||
control_flags.store(control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
control_flags.store(
|
||||
control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
|
||||
// Call handler, either sa_handler or sa_siginfo depending on flag.
|
||||
if sigaction.flags.contains(SigactionFlags::SIGINFO) && let Some(sigaction) = handler.sigaction {
|
||||
if sigaction.flags.contains(SigactionFlags::SIGINFO)
|
||||
&& let Some(sigaction) = handler.sigaction
|
||||
{
|
||||
//let _ = syscall::write(1, alloc::format!("SIGACTION {:p}\n", sigaction).as_bytes());
|
||||
sigaction(stack.sig_num as c_int, core::ptr::null_mut(), core::ptr::null_mut());
|
||||
sigaction(
|
||||
stack.sig_num as c_int,
|
||||
core::ptr::null_mut(),
|
||||
core::ptr::null_mut(),
|
||||
);
|
||||
} else if let Some(handler) = handler.handler {
|
||||
//let _ = syscall::write(1, alloc::format!("HANDLER {:p}\n", handler).as_bytes());
|
||||
handler(stack.sig_num as c_int);
|
||||
@@ -108,14 +132,23 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
//let _ = syscall::write(1, alloc::format!("RETURNED HANDLER\n").as_bytes());
|
||||
|
||||
// Disable signals while we modify the sigmask again
|
||||
control_flags.store(control_flags.load(Ordering::Relaxed) | SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
control_flags.store(
|
||||
control_flags.load(Ordering::Relaxed) | SigcontrolFlags::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
|
||||
// Update allowset again.
|
||||
//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 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
|
||||
@@ -126,7 +159,10 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
(*os.arch.get()).last_sig_was_restart = shall_restart;
|
||||
|
||||
// And re-enable them again
|
||||
control_flags.store(control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
control_flags.store(
|
||||
control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
}
|
||||
#[cfg(not(target_arch = "x86"))]
|
||||
@@ -144,14 +180,27 @@ pub fn get_sigmask() -> Result<u64> {
|
||||
Ok(mask)
|
||||
}
|
||||
pub fn set_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> {
|
||||
modify_sigmask(old, new.map(move |newmask| move |_, upper| if upper { newmask >> 32 } else { newmask } as u32))
|
||||
modify_sigmask(
|
||||
old,
|
||||
new.map(move |newmask| move |_, upper| if upper { newmask >> 32 } else { newmask } as u32),
|
||||
)
|
||||
}
|
||||
pub fn or_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> {
|
||||
// Parsing nightmare... :)
|
||||
modify_sigmask(old, new.map(move |newmask| move |oldmask, upper| oldmask | if upper { newmask >> 32 } else { newmask } as u32))
|
||||
modify_sigmask(
|
||||
old,
|
||||
new.map(move |newmask| {
|
||||
move |oldmask, upper| oldmask | if upper { newmask >> 32 } else { newmask } as u32
|
||||
}),
|
||||
)
|
||||
}
|
||||
pub fn andn_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> {
|
||||
modify_sigmask(old, new.map(move |newmask| move |oldmask, upper| oldmask & !if upper { newmask >> 32 } else { newmask } as u32))
|
||||
modify_sigmask(
|
||||
old,
|
||||
new.map(move |newmask| {
|
||||
move |oldmask, upper| oldmask & !if upper { newmask >> 32 } else { newmask } as u32
|
||||
}),
|
||||
)
|
||||
}
|
||||
fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32>) -> Result<()> {
|
||||
let _guard = tmp_disable_signals();
|
||||
@@ -174,7 +223,10 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
|
||||
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);
|
||||
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());
|
||||
|
||||
@@ -205,10 +257,12 @@ impl Sigaction {
|
||||
fn ip(&self) -> usize {
|
||||
unsafe {
|
||||
match self.kind {
|
||||
SigactionKind::Handled { handler } => if self.flags.contains(SigactionFlags::SIGINFO) {
|
||||
handler.sigaction.map_or(0, |a| a as usize)
|
||||
} else {
|
||||
handler.handler.map_or(0, |a| a as usize)
|
||||
SigactionKind::Handled { handler } => {
|
||||
if self.flags.contains(SigactionFlags::SIGINFO) {
|
||||
handler.sigaction.map_or(0, |a| a as usize)
|
||||
} else {
|
||||
handler.handler.map_or(0, |a| a as usize)
|
||||
}
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
@@ -230,7 +284,9 @@ fn convert_old(action: &RawAction) -> Sigaction {
|
||||
} else if flags.contains(SigactionFlags::IGNORED) {
|
||||
SigactionKind::Ignore
|
||||
} else {
|
||||
SigactionKind::Handled { handler: unsafe { core::mem::transmute(handler as usize) } }
|
||||
SigactionKind::Handled {
|
||||
handler: unsafe { core::mem::transmute(handler as usize) },
|
||||
}
|
||||
};
|
||||
|
||||
Sigaction {
|
||||
@@ -267,25 +323,33 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
|
||||
// TODO: POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
|
||||
// sigaction.
|
||||
// TODO: handle tmp_disable_signals
|
||||
(MASK_DONTCARE, SigactionFlags::IGNORED, if matches!(new.kind, SigactionKind::Default) {
|
||||
default_handler as usize
|
||||
} else {
|
||||
0
|
||||
})
|
||||
(
|
||||
MASK_DONTCARE,
|
||||
SigactionFlags::IGNORED,
|
||||
if matches!(new.kind, SigactionKind::Default) {
|
||||
default_handler as usize
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
}
|
||||
// TODO: Handle pending signals before these flags are set.
|
||||
(SIGTSTP | SIGTTOU | SIGTTIN, SigactionKind::Default) => (MASK_DONTCARE, SigactionFlags::SIG_SPECIFIC, default_handler as usize),
|
||||
(SIGTSTP | SIGTTOU | SIGTTIN, SigactionKind::Default) => (
|
||||
MASK_DONTCARE,
|
||||
SigactionFlags::SIG_SPECIFIC,
|
||||
default_handler as usize,
|
||||
),
|
||||
(SIGCHLD, SigactionKind::Default) => {
|
||||
let nocldstop_bit = new.flags & SigactionFlags::SIG_SPECIFIC;
|
||||
(MASK_DONTCARE, SigactionFlags::IGNORED | nocldstop_bit, default_handler as usize)
|
||||
(
|
||||
MASK_DONTCARE,
|
||||
SigactionFlags::IGNORED | nocldstop_bit,
|
||||
default_handler as usize,
|
||||
)
|
||||
}
|
||||
|
||||
(_, SigactionKind::Default) => {
|
||||
(new.mask, new.flags, default_handler as usize)
|
||||
},
|
||||
(_, SigactionKind::Handled { .. }) => {
|
||||
(new.mask, new.flags, explicit_handler)
|
||||
}
|
||||
(_, SigactionKind::Default) => (new.mask, new.flags, default_handler as usize),
|
||||
(_, SigactionKind::Handled { .. }) => (new.mask, new.flags, explicit_handler),
|
||||
};
|
||||
let new_first = (handler as u64) | (u64::from(flags.bits() & STORED_FLAGS) << 32);
|
||||
action.first.store(new_first, Ordering::Relaxed);
|
||||
@@ -298,12 +362,17 @@ fn current_sigctl() -> &'static Sigcontrol {
|
||||
&unsafe { Tcb::current() }.unwrap().os_specific.control
|
||||
}
|
||||
|
||||
pub struct TmpDisableSignalsGuard { _inner: () }
|
||||
pub struct TmpDisableSignalsGuard {
|
||||
_inner: (),
|
||||
}
|
||||
|
||||
pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
|
||||
unsafe {
|
||||
let ctl = ¤t_sigctl().control_flags;
|
||||
ctl.store(ctl.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
ctl.store(
|
||||
ctl.load(Ordering::Relaxed) | syscall::flag::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
|
||||
// TODO: fence?
|
||||
@@ -315,12 +384,16 @@ pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
|
||||
impl Drop for TmpDisableSignalsGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let depth = &mut (*Tcb::current().unwrap().os_specific.arch.get()).disable_signals_depth;
|
||||
let depth =
|
||||
&mut (*Tcb::current().unwrap().os_specific.arch.get()).disable_signals_depth;
|
||||
*depth -= 1;
|
||||
|
||||
if *depth == 0 {
|
||||
let ctl = ¤t_sigctl().control_flags;
|
||||
ctl.store(ctl.load(Ordering::Relaxed) & !syscall::flag::INHIBIT_DELIVERY.bits(), Ordering::Release);
|
||||
ctl.store(
|
||||
ctl.load(Ordering::Relaxed) & !syscall::flag::INHIBIT_DELIVERY.bits(),
|
||||
Ordering::Release,
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
}
|
||||
}
|
||||
@@ -389,7 +462,10 @@ pub fn setup_sighandler(area: &RtSigarea) {
|
||||
} else {
|
||||
SigactionFlags::empty()
|
||||
};
|
||||
action.first.store((u64::from(bits.bits()) << 32) | default_handler as u64, Ordering::Relaxed);
|
||||
action.first.store(
|
||||
(u64::from(bits.bits()) << 32) | default_handler as u64,
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
}
|
||||
}
|
||||
let arch = unsafe { &mut *area.arch.get() };
|
||||
@@ -433,7 +509,9 @@ pub fn current_setsighandler_struct() -> SetSighandlerData {
|
||||
SetSighandlerData {
|
||||
user_handler: sighandler_function(),
|
||||
excp_handler: 0, // TODO
|
||||
thread_control_addr: core::ptr::addr_of!(unsafe { Tcb::current() }.unwrap().os_specific.control) as usize,
|
||||
thread_control_addr: core::ptr::addr_of!(
|
||||
unsafe { Tcb::current() }.unwrap().os_specific.control
|
||||
) as usize,
|
||||
proc_control_addr: &PROC_CONTROL_STRUCT as *const SigProcControl as usize,
|
||||
}
|
||||
}
|
||||
@@ -443,9 +521,16 @@ pub enum Sigaltstack {
|
||||
#[default]
|
||||
Disabled,
|
||||
|
||||
Enabled { onstack: bool, base: *mut (), size: usize },
|
||||
Enabled {
|
||||
onstack: bool,
|
||||
base: *mut (),
|
||||
size: usize,
|
||||
},
|
||||
}
|
||||
pub unsafe fn sigaltstack(new: Option<&Sigaltstack>, old_out: Option<&mut Sigaltstack>) -> Result<()> {
|
||||
pub unsafe fn sigaltstack(
|
||||
new: Option<&Sigaltstack>,
|
||||
old_out: Option<&mut Sigaltstack>,
|
||||
) -> Result<()> {
|
||||
let _g = tmp_disable_signals();
|
||||
let tcb = &mut *Tcb::current().unwrap().os_specific.arch.get();
|
||||
|
||||
@@ -473,7 +558,11 @@ pub unsafe fn sigaltstack(new: Option<&Sigaltstack>, old_out: Option<&mut Sigalt
|
||||
tcb.altstack_top = usize::MAX;
|
||||
}
|
||||
Sigaltstack::Enabled { onstack: true, .. } => return Err(Error::new(EINVAL)),
|
||||
Sigaltstack::Enabled { base, size, onstack: false } => {
|
||||
Sigaltstack::Enabled {
|
||||
base,
|
||||
size,
|
||||
onstack: false,
|
||||
} => {
|
||||
if size < MIN_SIGALTSTACK_SIZE {
|
||||
return Err(Error::new(ENOMEM));
|
||||
}
|
||||
|
||||
+10
-4
@@ -1,8 +1,10 @@
|
||||
// TODO: Share code for simple futex-based mutex between relibc's Mutex<()> and this.
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
pub struct Mutex<T> {
|
||||
pub lockword: AtomicU32,
|
||||
@@ -24,7 +26,11 @@ impl<T> Mutex<T> {
|
||||
}
|
||||
}
|
||||
pub fn lock(&self) -> MutexGuard<'_, T> {
|
||||
while self.lockword.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed).is_err() {
|
||||
while self
|
||||
.lockword
|
||||
.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
MutexGuard { lock: self }
|
||||
|
||||
+35
-6
@@ -1,17 +1,20 @@
|
||||
use syscall::error::{Result, Error, EINTR};
|
||||
use syscall::{
|
||||
error::{Error, Result, EINTR},
|
||||
TimeSpec,
|
||||
};
|
||||
|
||||
use crate::arch::manually_enter_trampoline;
|
||||
use crate::signal::tmp_disable_signals;
|
||||
use crate::Tcb;
|
||||
use crate::{arch::manually_enter_trampoline, signal::tmp_disable_signals, Tcb};
|
||||
|
||||
#[inline]
|
||||
fn wrapper(mut f: impl FnMut() -> Result<usize>) -> Result<usize> {
|
||||
fn wrapper<T>(mut f: impl FnMut() -> Result<T>) -> Result<T> {
|
||||
loop {
|
||||
let _guard = tmp_disable_signals();
|
||||
let rt_sigarea = unsafe { &Tcb::current().unwrap().os_specific };
|
||||
let res = f();
|
||||
|
||||
if res == Err(Error::new(EINTR)) {
|
||||
if let Err(err) = res
|
||||
&& err == Error::new(EINTR)
|
||||
{
|
||||
unsafe {
|
||||
manually_enter_trampoline();
|
||||
}
|
||||
@@ -47,3 +50,29 @@ pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> {
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn sys_futex_wait(addr: *mut u32, val: u32, deadline: Option<&TimeSpec>) -> Result<()> {
|
||||
wrapper(|| {
|
||||
syscall::syscall5(
|
||||
syscall::SYS_FUTEX,
|
||||
addr as usize,
|
||||
syscall::FUTEX_WAIT,
|
||||
val as usize,
|
||||
deadline.map_or(0, |d| d as *const _ as usize),
|
||||
0,
|
||||
)
|
||||
.map(|_| ())
|
||||
})
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result<u32> {
|
||||
syscall::syscall5(
|
||||
syscall::SYS_FUTEX,
|
||||
addr as usize,
|
||||
syscall::FUTEX_WAKE,
|
||||
num as usize,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
.map(|awoken| awoken as u32)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use syscall::SetSighandlerData;
|
||||
use syscall::{Result, O_CLOEXEC};
|
||||
use syscall::{Result, SetSighandlerData, O_CLOEXEC};
|
||||
|
||||
use crate::arch::*;
|
||||
use crate::proc::*;
|
||||
use crate::signal::sighandler_function;
|
||||
use crate::{arch::*, proc::*, signal::sighandler_function};
|
||||
|
||||
/// Spawns a new context sharing the same address space as the current one (i.e. a new thread).
|
||||
pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> {
|
||||
|
||||
@@ -242,8 +242,9 @@ impl Pal for Sys {
|
||||
unsafe fn futex_wait(
|
||||
addr: *mut u32,
|
||||
val: u32,
|
||||
deadline: *const timespec,
|
||||
deadline: Option<×pec>,
|
||||
) -> Result<(), crate::pthread::Errno> {
|
||||
let deadline = deadline.map_or(0, |d| d as *const _ as usize);
|
||||
e_raw(unsafe {
|
||||
syscall!(
|
||||
FUTEX, addr, // uaddr
|
||||
@@ -257,11 +258,11 @@ impl Pal for Sys {
|
||||
.map(|_| ())
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, Errno> {
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<u32, Errno> {
|
||||
e_raw(unsafe {
|
||||
syscall!(FUTEX, addr, 1 /* FUTEX_WAKE */, num)
|
||||
})
|
||||
.map(|n| n as c_int)
|
||||
.map(|n| n as u32)
|
||||
}
|
||||
|
||||
fn futimens(fd: c_int, times: *const timespec) -> c_int {
|
||||
|
||||
@@ -82,9 +82,9 @@ pub trait Pal {
|
||||
unsafe fn futex_wait(
|
||||
addr: *mut u32,
|
||||
val: u32,
|
||||
deadline: *const timespec,
|
||||
deadline: Option<×pec>,
|
||||
) -> Result<(), pthread::Errno>;
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, pthread::Errno>;
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<u32, pthread::Errno>;
|
||||
|
||||
fn futimens(fd: c_int, times: *const timespec) -> c_int;
|
||||
|
||||
|
||||
+12
-25
@@ -1,4 +1,4 @@
|
||||
use core::{convert::TryFrom, mem, ptr, result::Result as CoreResult, slice, str};
|
||||
use core::{convert::TryFrom, mem, ptr, slice, str};
|
||||
use syscall::{
|
||||
self,
|
||||
data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec},
|
||||
@@ -305,31 +305,18 @@ impl Pal for Sys {
|
||||
unsafe fn futex_wait(
|
||||
addr: *mut u32,
|
||||
val: u32,
|
||||
deadline: *const timespec,
|
||||
) -> CoreResult<(), pthread::Errno> {
|
||||
syscall::syscall5(
|
||||
syscall::SYS_FUTEX,
|
||||
addr as usize,
|
||||
syscall::FUTEX_WAIT,
|
||||
val as usize,
|
||||
deadline as usize,
|
||||
0,
|
||||
)
|
||||
.map_err(|s| pthread::Errno(s.errno))
|
||||
.map(|_| ())
|
||||
deadline: Option<×pec>,
|
||||
) -> Result<(), pthread::Errno> {
|
||||
let deadline = deadline.map(|d| syscall::TimeSpec {
|
||||
tv_sec: d.tv_sec,
|
||||
tv_nsec: d.tv_nsec as i32,
|
||||
});
|
||||
redox_rt::sys::sys_futex_wait(addr, val, deadline.as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, pthread::Errno> {
|
||||
syscall::syscall5(
|
||||
syscall::SYS_FUTEX,
|
||||
addr as usize,
|
||||
syscall::FUTEX_WAKE,
|
||||
num as usize,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
.map_err(|s| pthread::Errno(s.errno))
|
||||
.map(|n| n as c_int)
|
||||
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<u32, pthread::Errno> {
|
||||
Ok(redox_rt::sys::sys_futex_wake(addr, num)?)
|
||||
}
|
||||
|
||||
// FIXME: unsound
|
||||
@@ -996,7 +983,7 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inner(utsname: *mut utsname) -> CoreResult<(), i32> {
|
||||
fn inner(utsname: *mut utsname) -> Result<(), i32> {
|
||||
match gethostname(unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
(*utsname).nodename.as_mut_ptr() as *mut u8,
|
||||
|
||||
+1
-5
@@ -102,11 +102,7 @@ pub unsafe fn futex_wait_ptr<T: FutexTy>(
|
||||
value: T,
|
||||
deadline_opt: Option<×pec>,
|
||||
) -> FutexWaitResult {
|
||||
match Sys::futex_wait(
|
||||
ptr.cast(),
|
||||
value.conv(),
|
||||
deadline_opt.map_or(core::ptr::null(), |t| t as *const _),
|
||||
) {
|
||||
match Sys::futex_wait(ptr.cast(), value.conv(), deadline_opt) {
|
||||
Ok(()) => FutexWaitResult::Waited,
|
||||
Err(Errno(EAGAIN)) => FutexWaitResult::Stale,
|
||||
Err(Errno(ETIMEDOUT)) if deadline_opt.is_some() => FutexWaitResult::TimedOut,
|
||||
|
||||
Reference in New Issue
Block a user