diff --git a/generic-rt/src/lib.rs b/generic-rt/src/lib.rs index 2999115c36508d048c38ec8bfb850c8be96b59f3..621cab3d480357241b5df6eea87504ec0b0e6831 100644 --- a/generic-rt/src/lib.rs +++ b/generic-rt/src/lib.rs @@ -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> { } } } - diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index e4a5e8b54cd990f63d1edb4ca3145ebd90a2fd0a..3379bca7f6fb3093686e99404a25d4073eca10cf 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -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; diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 80296b835a31bab94ba1767e79bcc9f681f71bf5..ec4decdde4bb3c0846522abfba8701599ac5bc2b 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -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!(" diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 4e53aef393de82b8927ad3ac45257000379cd769..73db7cea29c999a6339e1a1ae2292b06a0d87d0b 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -1,14 +1,19 @@ -use core::mem::offset_of; -use core::sync::atomic::{AtomicU8, Ordering}; - -use syscall::data::{Sigcontrol, SigProcControl}; -use syscall::error::*; -use syscall::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 core::{ + mem::offset_of, + sync::atomic::{AtomicU8, Ordering}, +}; + +use syscall::{ + data::{SigProcControl, Sigcontrol}, + error::*, + flag::*, +}; + +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!(" diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 8112c9b4335688c9ba074a12908d89fbc6812433..addc576dcfdd9f289eec2e64356b302585af0135 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -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; diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index a89354f274eca1ddda62ec20cd070d5d3fea3f4c..ff8ce2436021c1aad08d7e1b3ef25294d5600711 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -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)?; } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index c55b6f313c30b9d0766ed099bda1c4984494547b..9e777636606b9a3e79a28d3fd863ccff500c0b1b 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -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)); } diff --git a/redox-rt/src/sync.rs b/redox-rt/src/sync.rs index 172bd37b1f1c0d49af5e8b653387ce32f6b879ac..5b56434d70f53b6cc23ccb75d463a79d335a18f6 100644 --- a/redox-rt/src/sync.rs +++ b/redox-rt/src/sync.rs @@ -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 } diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index d450a5625a2bd4a1272ab64b18e3c3fd8610d486..29f7ef3350b14e610ddf5e9e53c07316b01ec2ac 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -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) +} diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 9b348a62d7445a0d6efaf1e913c6b5ce85be4ad9..b869b50b5bf4daa5e5203e2d88d89215366a879a 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -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> { diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 71f3ba0ce396794292b0db2df5a24d68f8b86258..1c645386a76758aa73601dbe5ed6aa9db6728fc5 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -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 { diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index ea226f7ad9ff027ed4741aa92886466384b5393b..8b30339e9e79eef1bafd1a2a4cdeb852b10658fd 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -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; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index c1d3b645f3b9788c6f8434d04a498a58423849b1..e6d415e0eb38719adb8881afcfd49d40ef162af0 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -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, diff --git a/src/sync/mod.rs b/src/sync/mod.rs index d851f925cad5e63d247ab4458cd9a54e171063f7..77bda2d964640c9b5fec2100e9d61cb123b97dae 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -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,