Skip to content

Commit

Permalink
Add vector clock to epoll
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankReh committed Sep 30, 2024
1 parent 71f296e commit 3a660db
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions src/shims/unix/linux/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io;
use std::rc::{Rc, Weak};
use std::time::Duration;

use crate::concurrency::{VClock, data_race};
use crate::shims::unix::fd::{FdId, FileDescriptionRef, WeakFileDescriptionRef};
use crate::shims::unix::*;
use crate::*;
Expand All @@ -19,7 +20,7 @@ struct Epoll {
/// and file descriptor value.
// This is an Rc because EpollInterest need to hold a reference to update
// it.
ready_list: Rc<RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>>,
ready_list: Rc<ReadyList>,
/// A list of thread ids blocked on this epoll instance.
thread_id: RefCell<Vec<ThreadId>>,
}
Expand Down Expand Up @@ -63,7 +64,7 @@ pub struct EpollEventInterest {
/// <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>
data: u64,
/// Ready list of the epoll instance under which this EpollEventInterest is registered.
ready_list: Rc<RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>>,
ready_list: Rc<ReadyList>,
/// The epoll file description that this EpollEventInterest is registered under.
weak_epfd: WeakFileDescriptionRef,
}
Expand All @@ -88,6 +89,12 @@ pub struct EpollReadyEvents {
pub epollerr: bool,
}

#[derive(Debug, Default)]
struct ReadyList {
mapping: RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>,
clock: RefCell<VClock>,
}

impl EpollReadyEvents {
pub fn new() -> Self {
EpollReadyEvents {
Expand Down Expand Up @@ -127,7 +134,7 @@ impl EpollReadyEvents {
}

impl Epoll {
fn get_ready_list(&self) -> Rc<RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>> {
fn get_ready_list(&self) -> Rc<ReadyList> {
Rc::clone(&self.ready_list)
}
}
Expand Down Expand Up @@ -186,7 +193,9 @@ impl EpollInterestTable {
}

impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
pub trait EvalContextExt<'tcx>:
crate::MiriInterpCxExt<'tcx> + data_race::EvalContextExt<'tcx>
{
/// This function returns a file descriptor referring to the new `Epoll` instance. This file
/// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument
/// is 0, then this function is the same as `epoll_create()`.
Expand All @@ -207,9 +216,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
);
}

let mut epoll_instance = Epoll::default();
epoll_instance.ready_list = Rc::new(RefCell::new(BTreeMap::new()));

let fd = this.machine.fds.insert_new(Epoll::default());
Ok(Scalar::from_i32(fd))
}
Expand Down Expand Up @@ -378,7 +384,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
drop(epoll_interest);

// Remove related epoll_interest from ready list.
ready_list.borrow_mut().remove(&epoll_key);
ready_list.mapping.borrow_mut().remove(&epoll_key);

// Remove dangling EpollEventInterest from its global table.
// .unwrap() below should succeed because the file description id must have registered
Expand Down Expand Up @@ -473,8 +479,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let epoll_file_description = epfd
.downcast::<Epoll>()
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;
let binding = epoll_file_description.get_ready_list();
ready_list_empty = binding.borrow_mut().is_empty();
ready_list_empty = epoll_file_description.ready_list.mapping.borrow().is_empty();
thread_ids = epoll_file_description.thread_id.borrow_mut();
}
if timeout == 0 || !ready_list_empty {
Expand Down Expand Up @@ -563,9 +568,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// holds a strong ref to epoll_interest.
let epfd = epoll_interest.borrow().weak_epfd.upgrade().unwrap();
// FIXME: We can randomly pick a thread to unblock.
if let Some(thread_id) =
epfd.downcast::<Epoll>().unwrap().thread_id.borrow_mut().pop()
{

let epoll = epfd.downcast::<Epoll>().unwrap();

// Synchronize running thread to the epoll ready list.
if let Some(clock) = &this.release_clock() {
epoll.ready_list.clock.borrow_mut().join(clock);
}

if let Some(thread_id) = epoll.thread_id.borrow_mut().pop() {
waiter.push(thread_id);
};
}
Expand Down Expand Up @@ -619,7 +630,7 @@ fn check_and_update_one_event_interest<'tcx>(
// insert an epoll_return to the ready list.
if flags != 0 {
let epoll_key = (id, epoll_event_interest.fd_num);
let ready_list = &mut epoll_event_interest.ready_list.borrow_mut();
let ready_list = &mut epoll_event_interest.ready_list.mapping.borrow_mut();
let event_instance = EpollEventInstance::new(flags, epoll_event_interest.data);
// Triggers the notification by inserting it to the ready list.
ready_list.insert(epoll_key, event_instance);
Expand All @@ -646,7 +657,11 @@ fn blocking_epoll_callback<'tcx>(
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?;

let ready_list = epoll_file_description.get_ready_list();
let mut ready_list = ready_list.borrow_mut();

// 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)?;

Expand Down

0 comments on commit 3a660db

Please sign in to comment.