-
Notifications
You must be signed in to change notification settings - Fork 347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add vector clock to epoll ready lists #3932
Conversation
This test demonstrates the need to synchronize the clock of the thread waking up from an epoll_wait from the thread that issued the epoll awake event.
A couple of instructions were left over from an earlier rebase it would seem. They don't impact the logic but the ready_list type is about to change in the next commit. Rather than modify one of these lines in the commit that changes ready_list, only to have these lines removed later on, remove them now. They don't impact the tests results.
This adds a VClock to the epoll implementation's ready_list and has this VClock synced from the thread that updates an event in the ready_list and then has the VClocks of any threads being made runnable again, out of the calls to epoll_wait, synced from it.
A simplification that doesn't impact the epoll implementation's logic. It is not necessary to clone the ready_list before reading its `is_empty` state. This avoids the clone step but more importantly avoids the invisible drop step of the clone.
@bors r+ |
☀️ Test successful - checks-actions |
#[derive(Debug, Default)] | ||
struct ReadyList { | ||
mapping: RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>, | ||
clock: RefCell<VClock>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we say in the issue that we wanted a clock per event?
That would avoid accidentally synchronizing with events we didn't even receive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RalfJung Do you feel this synch is too broad?
/// Callback function after epoll_wait unblocks
fn blocking_epoll_callback<'tcx>(
epfd_value: i32,
weak_epfd: WeakFileDescriptionRef,
dest: &MPlaceTy<'tcx>,
events: &MPlaceTy<'tcx>,
ecx: &mut MiriInterpCx<'tcx>,
) -> InterpResult<'tcx> {
let Some(epfd) = weak_epfd.upgrade() else {
throw_unsup_format!("epoll FD {epfd_value} got closed while blocking.")
};
let epoll_file_description = epfd
.downcast::<Epoll>()
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
let ready_list = epoll_file_description.get_ready_list();
// Synchronize waking thread from the epoll ready list.
ecx.acquire_clock(&ready_list.clock.borrow());
let mut ready_list = ready_list.mapping.borrow_mut();
let mut num_of_events: i32 = 0;
let mut array_iter = ecx.project_array_fields(events)?;
while let Some(des) = array_iter.next(ecx)? {
if let Some(epoll_event_instance) = ready_list_next(ecx, &mut ready_list) {
ecx.write_int_fields_named(
&[
("events", epoll_event_instance.events.into()),
("u64", epoll_event_instance.data.into()),
],
&des.1,
)?;
num_of_events = num_of_events.strict_add(1);
} else {
break;
}
}
ecx.write_int(num_of_events, dest)?;
interp_ok(())
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what you are currently doing, right? Yes I think this syncs too much: #3944
Replaces #3928
Fixes #3911