Add futex timeout

This commit is contained in:
Jeremy Soller
2017-11-06 22:04:42 -07:00
parent 2de7bd7f79
commit 9e9f80ef13
2 changed files with 47 additions and 15 deletions

26
Cargo.lock generated
View File

@@ -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"

View File

@@ -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<RwLock<Context>>)>;
@@ -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<usize> {
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 => {