Kaynağa Gözat

Enable getitimer, setitimer, and sigprocmask

Jeremy Soller 6 yıl önce
ebeveyn
işleme
083642fb17

+ 6 - 6
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"

+ 9 - 14
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<extern "C" fn(c_int)>,
+    pub sa_handler: extern "C" fn(c_int),
     pub sa_flags: c_ulong,
-    pub sa_restorer: Option<unsafe extern "C" fn()>,
+    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<extern "C" fn(c_int)>,
-) -> Option<extern "C" fn(c_int)> {
+    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 {

+ 13 - 13
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 {

+ 43 - 43
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 {

+ 1 - 8
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 }
     // }

+ 12 - 5
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};
+use header::sys_time::itimerval;
 
-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::<sigset_t>()) }) as c_int
+impl PalSignal for Sys {
+    fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
+        e(unsafe { syscall!(GETITIMER, which, out) }) as c_int
     }
-}
 
-impl PalSignal for Sys {
     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::<sigset_t>()
         )) 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::<sigset_t>()) }) as c_int
+    }
 }

+ 8 - 1
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;
 }

+ 114 - 23
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;
+use header::errno::EINVAL;
+use header::signal::{sigaction, sigset_t};
+use header::sys_time::itimerval;
 
-#[thread_local]
-static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
+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;
+        }
 
-extern "C" fn sig_handler(sig: usize) {
-    if let Some(ref callback) = unsafe { SIG_HANDLER } {
-        callback(sig as c_int);
+        0
     }
-}
 
-impl PalSignal for Sys {
     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
+    }
 }