Enable syscall restart in futex_wait.

This commit is contained in:
4lDO2
2024-07-16 11:55:06 +02:00
parent bcce7e18db
commit 4c20a9abb2
14 changed files with 292 additions and 151 deletions
+4 -3
View File
@@ -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> {
}
}
}
+6 -6
View File
@@ -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;
+11 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 = &current_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 = &current_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
View File
@@ -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
View File
@@ -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)
}
+2 -5
View File
@@ -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> {
+4 -3
View File
@@ -242,8 +242,9 @@ impl Pal for Sys {
unsafe fn futex_wait(
addr: *mut u32,
val: u32,
deadline: *const timespec,
deadline: Option<&timespec>,
) -> 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 {
+2 -2
View File
@@ -82,9 +82,9 @@ pub trait Pal {
unsafe fn futex_wait(
addr: *mut u32,
val: u32,
deadline: *const timespec,
deadline: Option<&timespec>,
) -> 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
View File
@@ -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<&timespec>,
) -> 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
View File
@@ -102,11 +102,7 @@ pub unsafe fn futex_wait_ptr<T: FutexTy>(
value: T,
deadline_opt: Option<&timespec>,
) -> 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,