From 9e9f80ef13bfa4aa03c29db35cc67de97bd1f5e7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 6 Nov 2017 22:04:42 -0700 Subject: [PATCH] Add futex timeout --- Cargo.lock | 26 +++++++++++++------------- src/syscall/futex.rs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a00081d..d88a77e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,3 @@ -[root] -name = "kernel" -version = "0.1.0" -dependencies = [ - "alloc_kernel 0.1.0", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "raw-cpuid 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31", - "spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "alloc_kernel" version = "0.1.0" @@ -43,6 +30,19 @@ dependencies = [ "scroll 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kernel" +version = "0.1.0" +dependencies = [ + "alloc_kernel 0.1.0", + "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.31", + "spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "linked_list_allocator" version = "0.4.1" diff --git a/src/syscall/futex.rs b/src/syscall/futex.rs index 7a2500b..c38fce9 100644 --- a/src/syscall/futex.rs +++ b/src/syscall/futex.rs @@ -4,9 +4,11 @@ use core::intrinsics; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use context::{self, Context}; +use time; +use syscall::data::TimeSpec; use syscall::error::{Error, Result, ESRCH, EAGAIN, EINVAL}; use syscall::flag::{FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; -use syscall::validate::validate_slice_mut; +use syscall::validate::{validate_slice, validate_slice_mut}; type FutexList = VecDeque<(usize, Arc>)>; @@ -31,6 +33,12 @@ pub fn futexes_mut() -> RwLockWriteGuard<'static, FutexList> { pub fn futex(addr: &mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { match op { FUTEX_WAIT => { + let timeout_opt = if val2 != 0 { + Some(validate_slice(val2 as *const TimeSpec, 1).map(|req| &req[0])?) + } else { + None + }; + { let mut futexes = futexes_mut(); @@ -44,13 +52,37 @@ pub fn futex(addr: &mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) return Err(Error::new(EAGAIN)); } - context_lock.write().block(); + { + let mut context = context_lock.write(); + + if let Some(timeout) = timeout_opt { + let start = time::monotonic(); + let sum = start.1 + timeout.tv_nsec as u64; + let end = (start.0 + timeout.tv_sec as u64 + sum / 1000000000, sum % 1000000000); + context.wake = Some(end); + } + + context.block(); + } futexes.push_back((addr as *mut i32 as usize, context_lock)); } unsafe { context::switch(); } + if timeout_opt.is_some() { + let context_lock = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + context_lock.clone() + }; + + { + let mut context = context_lock.write(); + context.wake = None; + } + } + Ok(0) }, FUTEX_WAKE => {