Skip to content

Commit 9644150

Browse files
committed
Handle timeout and refactor the blocking logic in epoll_wait
1 parent a97a99e commit 9644150

File tree

1 file changed

+36
-35
lines changed

1 file changed

+36
-35
lines changed

src/shims/unix/linux/epoll.rs

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
430430
let epfd_value = this.read_scalar(epfd)?.to_i32()?;
431431
let events = this.read_immediate(events_op)?;
432432
let maxevents = this.read_scalar(maxevents)?.to_i32()?;
433-
let timeout = this.read_scalar(timeout)?.to_u32()?;
433+
let timeout = this.read_scalar(timeout)?.to_i32()?;
434434

435435
if epfd_value <= 0 || maxevents <= 0 {
436436
let einval = this.eval_libc("EINVAL");
@@ -467,42 +467,43 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
467467
ready_list_empty = binding.borrow_mut().is_empty();
468468
thread_ids = epoll_file_description.thread_id.borrow_mut();
469469
}
470-
471-
if ready_list_empty {
472-
if timeout == 0 {
473-
// Non-blocking with no notification returned.
474-
this.write_scalar(Scalar::from_i32(0), &dest)?;
475-
} else {
476-
// Blocking
477-
let duration = Duration::from_millis(timeout.into());
478-
thread_ids.push(this.active_thread());
479-
this.block_thread(
480-
BlockReason::Epoll,
481-
Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration)),
482-
callback!(
483-
@capture<'tcx> {
484-
epfd_value: i32,
485-
weak_epfd: WeakFileDescriptionRef,
486-
dest: MPlaceTy<'tcx>,
487-
event: MPlaceTy<'tcx>,
488-
}
489-
@unblock = |this| {
490-
this.blocking_epoll_callback(epfd_value, weak_epfd, &dest, &event)?;
491-
Ok(())
492-
}
493-
@timeout = |this| {
494-
// No notification after blocking timeout.
495-
this.write_scalar(Scalar::from_i32(0), &dest)?;
496-
Ok(())
497-
}
498-
),
499-
);
500-
}
501-
} else {
502-
// Immediately return epoll notification without blocking.
470+
if timeout == 0 || !ready_list_empty {
471+
// If the ready list is not empty, or the timeout is 0, we can return immediately.
503472
this.blocking_epoll_callback(epfd_value, weak_epfd, &dest, &event)?;
473+
} else {
474+
// Blocking
475+
let timeout = match timeout {
476+
0.. => {
477+
let duration = Duration::from_millis(timeout.try_into().unwrap());
478+
Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration))
479+
}
480+
// If timeout value less than 0, block indefinitely until a notification
481+
// is returned.
482+
..0 => None,
483+
};
484+
thread_ids.push(this.active_thread());
485+
this.block_thread(
486+
BlockReason::Epoll,
487+
timeout,
488+
callback!(
489+
@capture<'tcx> {
490+
epfd_value: i32,
491+
weak_epfd: WeakFileDescriptionRef,
492+
dest: MPlaceTy<'tcx>,
493+
event: MPlaceTy<'tcx>,
494+
}
495+
@unblock = |this| {
496+
this.blocking_epoll_callback(epfd_value, weak_epfd, &dest, &event)?;
497+
Ok(())
498+
}
499+
@timeout = |this| {
500+
// No notification after blocking timeout.
501+
this.write_scalar(Scalar::from_i32(0), &dest)?;
502+
Ok(())
503+
}
504+
),
505+
);
504506
}
505-
506507
Ok(())
507508
}
508509

0 commit comments

Comments
 (0)