diff --git a/Cargo.lock b/Cargo.lock index c13dd4d161..2b715a989d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -176,7 +176,7 @@ dependencies = [ name = "ralloc_shim" version = "0.1.1" dependencies = [ - "redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -213,7 +213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_syscall" -version = "0.1.45" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -221,7 +221,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -236,7 +236,7 @@ dependencies = [ "posix-regex 0.1.0", "ralloc 1.0.0", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "va_list 0.1.0", @@ -371,7 +371,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -472,7 +472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" -"checksum redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)" = "7b7aac97a11cf928b13c97f726b1bfe8542969fcbc39007ce566a888da5964a3" +"checksum redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f22c50afdcf3f0a31ebb6b47697f6a7c5e5a24967e842858118bce0615f0afad" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 688f592b53..04200a0396 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -30,14 +30,9 @@ pub const SIG_SETMASK: c_int = 2; #[repr(C)] #[derive(Clone)] pub struct sigaction { - // I don't actually want these to be optional. They can have more than just - // one invalid value. But because of rust's non-null optimization, this - // causes Some(sigaction) with a null sa_handler to become None. Maybe - // these should be usizes and transmuted when needed... However, then I - // couldn't let cbindgen do its job. - pub sa_handler: Option, + pub sa_handler: extern "C" fn(c_int), pub sa_flags: c_ulong, - pub sa_restorer: Option, + pub sa_restorer: unsafe extern "C" fn(), pub sa_mask: sigset_t, } @@ -150,12 +145,12 @@ extern "C" { #[no_mangle] pub extern "C" fn signal( sig: c_int, - func: Option, -) -> Option { + func: extern "C" fn(c_int), +) -> extern "C" fn(c_int) { let sa = sigaction { sa_handler: func, sa_flags: SA_RESTART as c_ulong, - sa_restorer: Some(__restore_rt), + sa_restorer: __restore_rt, sa_mask: sigset_t::default(), }; let mut old_sa = unsafe { mem::uninitialized() }; @@ -176,10 +171,10 @@ pub extern "C" fn sigpending(set: *mut sigset_t) -> c_int { unimplemented!(); } -// #[no_mangle] -// pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { -// Sys::sigprocmask(how, set, oset) -// } +#[no_mangle] +pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { + Sys::sigprocmask(how, set, oset) +} // #[no_mangle] pub extern "C" fn sigrelse(sig: c_int) -> c_int { diff --git a/src/header/sys_time/mod.rs b/src/header/sys_time/mod.rs index efa185ff40..a57a967561 100644 --- a/src/header/sys_time/mod.rs +++ b/src/header/sys_time/mod.rs @@ -3,7 +3,7 @@ use c_str::CStr; use header::time::timespec; use platform::types::*; -use platform::{Pal, Sys}; +use platform::{Pal, PalSignal, Sys}; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; @@ -34,19 +34,19 @@ pub struct fd_set { pub fds_bits: [c_long; 16usize], } -// #[no_mangle] -// pub extern "C" fn getitimer(which: c_int, value: *mut itimerval) -> c_int { -// Sys::getitimer(which, value) -// } +#[no_mangle] +pub extern "C" fn getitimer(which: c_int, value: *mut itimerval) -> c_int { + Sys::getitimer(which, value) +} -// #[no_mangle] -// pub extern "C" fn setitimer( -// which: c_int, -// value: *const itimerval, -// ovalue: *mut itimerval, -// ) -> c_int { -// Sys::setitimer(which, value, ovalue) -// } +#[no_mangle] +pub extern "C" fn setitimer( + which: c_int, + value: *const itimerval, + ovalue: *mut itimerval, +) -> c_int { + Sys::setitimer(which, value, ovalue) +} #[no_mangle] pub extern "C" fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int { diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index eda8565556..6be06d87b4 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -6,6 +6,7 @@ use c_str::CStr; use header::errno; use header::limits; use header::stdlib::getenv; +use header::sys_time; use header::time::timespec; use platform; use platform::types::*; @@ -50,25 +51,24 @@ pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int { #[no_mangle] pub extern "C" fn alarm(seconds: c_uint) -> c_uint { - // let mut timer = sys_time::itimerval { - // it_value: sys_time::timeval { - // tv_sec: seconds as time_t, - // tv_usec: 0, - // }, - // ..Default::default() - // }; - // let errno_backup = unsafe { platform::errno }; - // let secs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 { - // 0 - // } else { - // timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 } - // }; - // unsafe { - // platform::errno = errno_backup; - // } - // - // secs - 0 + let mut timer = sys_time::itimerval { + it_value: sys_time::timeval { + tv_sec: seconds as time_t, + tv_usec: 0, + }, + ..Default::default() + }; + let errno_backup = unsafe { platform::errno }; + let secs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 { + 0 + } else { + timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 } + }; + unsafe { + platform::errno = errno_backup; + } + + secs } #[no_mangle] @@ -582,30 +582,30 @@ pub extern "C" fn ttyname_r(fildes: c_int, name: *mut c_char, namesize: size_t) unimplemented!(); } -// #[no_mangle] -// pub extern "C" fn ualarm(value: useconds_t, interval: useconds_t) -> useconds_t { -// let mut timer = sys_time::itimerval { -// it_value: sys_time::timeval { -// tv_sec: 0, -// tv_usec: value as suseconds_t, -// }, -// it_interval: sys_time::timeval { -// tv_sec: 0, -// tv_usec: interval as suseconds_t, -// }, -// }; -// let errno_backup = unsafe { platform::errno }; -// let usecs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 { -// 0 -// } else { -// timer.it_value.tv_sec as useconds_t * 1_000_000 + timer.it_value.tv_usec as useconds_t -// }; -// unsafe { -// platform::errno = errno_backup; -// } -// -// usecs -// } +#[no_mangle] +pub extern "C" fn ualarm(value: useconds_t, interval: useconds_t) -> useconds_t { + let mut timer = sys_time::itimerval { + it_value: sys_time::timeval { + tv_sec: 0, + tv_usec: value as suseconds_t, + }, + it_interval: sys_time::timeval { + tv_sec: 0, + tv_usec: interval as suseconds_t, + }, + }; + let errno_backup = unsafe { platform::errno }; + let usecs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 { + 0 + } else { + timer.it_value.tv_sec as useconds_t * 1_000_000 + timer.it_value.tv_usec as useconds_t + }; + unsafe { + platform::errno = errno_backup; + } + + usecs +} #[no_mangle] pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int { diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 30f9405116..f6c13b9cd3 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -15,7 +15,7 @@ use header::sys_ioctl::{winsize, TCGETS, TCSETS, TIOCGWINSZ}; use header::sys_select::fd_set; use header::sys_stat::stat; use header::sys_statvfs::statvfs; -use header::sys_time::{itimerval, timeval, timezone}; +use header::sys_time::{timeval, timezone}; // use header::sys_times::tms; use header::sys_utsname::utsname; use header::termios::termios; @@ -59,9 +59,6 @@ fn e(sys: usize) -> usize { pub struct Sys; impl Sys { - fn getitimer(which: c_int, out: *mut itimerval) -> c_int { - e(unsafe { syscall!(GETITIMER, which, out) }) as c_int - } // fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int { // e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int @@ -72,10 +69,6 @@ impl Sys { e(unsafe { syscall!(IOCTL, fd, request, out) }) as c_int } - fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int { - e(unsafe { syscall!(SETITIMER, which, new, old) }) as c_int - } - // fn times(out: *mut tms) -> clock_t { // unsafe { syscall!(TIMES, out) as clock_t } // } diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs index 46a2cf22eb..7680a9f867 100644 --- a/src/platform/linux/signal.rs +++ b/src/platform/linux/signal.rs @@ -4,14 +4,13 @@ use super::super::types::*; use super::super::PalSignal; use super::{e, Sys}; use header::signal::{sigaction, sigset_t}; - -impl Sys { - fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { - e(unsafe { syscall!(RT_SIGPROCMASK, how, set, oset, mem::size_of::()) }) as c_int - } -} +use header::sys_time::itimerval; impl PalSignal for Sys { + fn getitimer(which: c_int, out: *mut itimerval) -> c_int { + e(unsafe { syscall!(GETITIMER, which, out) }) as c_int + } + fn kill(pid: pid_t, sig: c_int) -> c_int { e(unsafe { syscall!(KILL, pid, sig) }) as c_int } @@ -29,6 +28,10 @@ impl PalSignal for Sys { } } + fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int { + e(unsafe { syscall!(SETITIMER, which, new, old) }) as c_int + } + unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int { e(syscall!( RT_SIGACTION, @@ -38,4 +41,8 @@ impl PalSignal for Sys { mem::size_of::() )) as c_int } + + fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { + e(unsafe { syscall!(RT_SIGPROCMASK, how, set, oset, mem::size_of::()) }) as c_int + } } diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs index 644012e8be..60a633c248 100644 --- a/src/platform/pal/signal.rs +++ b/src/platform/pal/signal.rs @@ -1,13 +1,20 @@ use super::super::types::*; use super::super::Pal; -use header::signal::sigaction; +use header::signal::{sigaction, sigset_t}; +use header::sys_time::itimerval; pub trait PalSignal: Pal { + fn getitimer(which: c_int, out: *mut itimerval) -> c_int; + fn kill(pid: pid_t, sig: c_int) -> c_int; fn killpg(pgrp: pid_t, sig: c_int) -> c_int; fn raise(sig: c_int) -> c_int; + fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int; + unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int; + + fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int; } diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 1677a2c0b4..d070ff2492 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -1,20 +1,48 @@ +use core::mem; use syscall; +use platform::errno; use super::super::types::*; use super::super::{Pal, PalSignal}; use super::{e, Sys}; -use header::signal::sigaction; - -#[thread_local] -static mut SIG_HANDLER: Option = None; - -extern "C" fn sig_handler(sig: usize) { - if let Some(ref callback) = unsafe { SIG_HANDLER } { - callback(sig as c_int); - } -} +use header::errno::EINVAL; +use header::signal::{sigaction, sigset_t}; +use header::sys_time::itimerval; impl PalSignal for Sys { + fn getitimer(which: c_int, out: *mut itimerval) -> c_int { + let path = match which { + ITIMER_REAL => "itimer:1", + _ => unsafe { + errno = EINVAL; + return -1; + } + }; + + let fd = e(syscall::open(path, syscall::O_RDONLY | syscall::O_CLOEXEC)); + if fd < 0 { + return -1; + } + + let mut spec = syscall::ITimerSpec::default(); + let count = e(syscall::read(fd, &mut spec)); + + let _ = syscall::close(fd); + + if count < 0 { + return -1; + } + + unsafe { + (*out).it_interval.tv_sec = spec.it_interval.tv_sec; + (*out).it_interval.tv_usec = spec.it_interval.tv_nsec/1000; + (*out).it_value.tv_sec = spec.it_value.tv_sec; + (*out).it_value.tv_usec = spec.it_value.tv_nsec/1000; + } + + 0 + } + fn kill(pid: pid_t, sig: c_int) -> c_int { e(syscall::kill(pid as usize, sig as usize)) as c_int } @@ -27,37 +55,100 @@ impl PalSignal for Sys { Self::kill(Self::getpid(), sig) } - unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int { - if !oact.is_null() { - // Assumes the last sigaction() call was made by relibc and not a different one - if SIG_HANDLER.is_some() { - (*oact).sa_handler = SIG_HANDLER; + fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int { + let path = match which { + ITIMER_REAL => "itimer:1", + _ => unsafe { + errno = EINVAL; + return -1; } + }; + + let fd = e(syscall::open(path, syscall::O_RDWR | syscall::O_CLOEXEC)); + if fd < 0 { + return -1; } - let act = if act.is_null() { + + let mut spec = syscall::ITimerSpec::default(); + + let mut count = e(syscall::read(fd, &mut spec)); + + if count >= 0 { + unsafe { + if ! old.is_null() { + (*old).it_interval.tv_sec = spec.it_interval.tv_sec; + (*old).it_interval.tv_usec = spec.it_interval.tv_nsec/1000; + (*old).it_value.tv_sec = spec.it_value.tv_sec; + (*old).it_value.tv_usec = spec.it_value.tv_nsec/1000; + } + + spec.it_interval.tv_sec = (*new).it_interval.tv_sec; + spec.it_interval.tv_nsec = (*new).it_interval.tv_usec * 1000; + spec.it_value.tv_sec = (*new).it_value.tv_sec; + spec.it_value.tv_nsec = (*new).it_value.tv_usec * 1000; + } + + count = e(syscall::write(fd, &spec)); + } + + let _ = syscall::close(fd); + + if count < 0 { + return -1; + } + + 0 + } + + unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int { + let new_opt = if act.is_null() { None } else { - SIG_HANDLER = (*act).sa_handler; let m = (*act).sa_mask; Some(syscall::SigAction { - sa_handler: sig_handler, - sa_mask: [0, m as u64], + sa_handler: mem::transmute((*act).sa_handler), + sa_mask: [m as u64, 0], sa_flags: (*act).sa_flags as usize, }) }; - let mut old = syscall::SigAction::default(); + let mut old_opt = if oact.is_null() { + None + } else { + Some(syscall::SigAction::default()) + }; let ret = e(syscall::sigaction( sig as usize, - act.as_ref(), - if oact.is_null() { None } else { Some(&mut old) }, + new_opt.as_ref(), + old_opt.as_mut(), )) as c_int; - if !oact.is_null() { + if let Some(old) = old_opt { + (*oact).sa_handler = mem::transmute(old.sa_handler); let m = old.sa_mask; - (*oact).sa_mask = m[1] as c_ulong; + (*oact).sa_mask = m[0] as c_ulong; (*oact).sa_flags = old.sa_flags as c_ulong; } ret } - //fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int; + fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { + let new_opt = if set.is_null() { + None + } else { + Some([unsafe { *set as u64 }, 0]) + }; + let mut old_opt = if oset.is_null() { + None + } else { + Some([0, 0]) + }; + let ret = e(syscall::sigprocmask( + how as usize, + new_opt.as_ref(), + old_opt.as_mut(), + )) as c_int; + if let Some(old) = old_opt { + unsafe { *oset = old[0] as sigset_t }; + } + ret + } }