Handle spurious wakeups in wait_timeout_sgx

This commit is contained in:
Mohsen Zohrevandi 2020-06-12 12:06:41 -07:00
parent c4b02659c1
commit d7dc64bdfe
3 changed files with 14 additions and 6 deletions

View file

@ -115,9 +115,15 @@ pub fn decode_error_kind(code: i32) -> ErrorKind {
// timeouts in SGX model. The enclave runner serving usercalls may lie about
// current time and/or ignore timeout values.
//
// Once the event is observed, `stop` will be used to determine whether or not
// we should continue to wait.
//
// FIXME: note these caveats in documentation of all public types that use this
// function in their execution path.
pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration) {
pub fn wait_timeout_sgx<F>(event_mask: u64, duration: crate::time::Duration, stop: F)
where
F: Fn() -> bool,
{
use self::abi::usercalls;
use crate::cmp;
use crate::io::ErrorKind;
@ -129,11 +135,13 @@ pub fn wait_timeout_sgx(event_mask: u64, duration: crate::time::Duration) {
let timeout = cmp::min((u64::MAX - 1) as u128, remaining.as_nanos()) as u64;
match usercalls::wait(event_mask, timeout) {
Ok(eventset) => {
if event_mask != 0 {
rtassert!(eventset & event_mask == event_mask);
if event_mask == 0 {
rtabort!("expected usercalls::wait() to return Err, found Ok.");
}
rtassert!(eventset & event_mask == event_mask);
if stop() {
return;
}
rtabort!("expected usercalls::wait() to return Err, found Ok.");
}
Err(e) => {
rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock)

View file

@ -76,7 +76,7 @@ impl Thread {
}
pub fn sleep(dur: Duration) {
wait_timeout_sgx(0, dur);
wait_timeout_sgx(0, dur, || true);
}
pub fn join(self) {

View file

@ -177,7 +177,7 @@ impl WaitQueue {
let entry_lock = lock.lock().queue.inner.push(&mut entry);
before_wait();
// don't panic, this would invalidate `entry` during unwinding
wait_timeout_sgx(EV_UNPARK, timeout);
wait_timeout_sgx(EV_UNPARK, timeout, || entry_lock.lock().wake);
// acquire the wait queue's lock first to avoid deadlock.
let mut guard = lock.lock();
let entry_guard = entry_lock.lock();