Skip to content

Commit cabc386

Browse files
authored
Merge pull request rust-lang#4115 from RalfJung/epoll
epoll: avoid some clones
2 parents 6365292 + bf9a76e commit cabc386

File tree

2 files changed

+40
-41
lines changed

2 files changed

+40
-41
lines changed

src/tools/miri/src/shims/files.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@ impl<T: ?Sized> FileDescriptionRef<T> {
5050
}
5151

5252
/// Holds a weak reference to the actual file description.
53-
#[derive(Clone, Debug)]
53+
#[derive(Debug)]
5454
pub struct WeakFileDescriptionRef<T: ?Sized>(Weak<FdIdWith<T>>);
5555

56+
impl<T: ?Sized> Clone for WeakFileDescriptionRef<T> {
57+
fn clone(&self) -> Self {
58+
WeakFileDescriptionRef(self.0.clone())
59+
}
60+
}
61+
5662
impl<T: ?Sized> FileDescriptionRef<T> {
5763
pub fn downgrade(this: &Self) -> WeakFileDescriptionRef<T> {
5864
WeakFileDescriptionRef(Rc::downgrade(&this.0))

src/tools/miri/src/shims/unix/linux_like/epoll.rs

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,15 @@ use crate::shims::unix::UnixFileDescription;
1212
use crate::*;
1313

1414
/// An `Epoll` file descriptor connects file handles and epoll events
15-
#[derive(Clone, Debug, Default)]
15+
#[derive(Debug, Default)]
1616
struct Epoll {
1717
/// A map of EpollEventInterests registered under this epoll instance.
1818
/// Each entry is differentiated using FdId and file descriptor value.
1919
interest_list: RefCell<BTreeMap<(FdId, i32), Rc<RefCell<EpollEventInterest>>>>,
2020
/// A map of EpollEventInstance that will be returned when `epoll_wait` is called.
2121
/// Similar to interest_list, the entry is also differentiated using FdId
2222
/// and file descriptor value.
23-
// This is an Rc because EpollInterest need to hold a reference to update
24-
// it.
25-
ready_list: Rc<ReadyList>,
23+
ready_list: ReadyList,
2624
/// A list of thread ids blocked on this epoll instance.
2725
blocked_tid: RefCell<Vec<ThreadId>>,
2826
}
@@ -59,7 +57,7 @@ impl EpollEventInstance {
5957
/// see the man page:
6058
///
6159
/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
62-
#[derive(Clone, Debug)]
60+
#[derive(Debug)]
6361
pub struct EpollEventInterest {
6462
/// The file descriptor value of the file description registered.
6563
/// This is only used for ready_list, to inform userspace which FD triggered an event.
@@ -73,9 +71,9 @@ pub struct EpollEventInterest {
7371
/// but only u64 is supported for now.
7472
/// <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>
7573
data: u64,
76-
/// Ready list of the epoll instance under which this EpollEventInterest is registered.
77-
ready_list: Rc<ReadyList>,
7874
/// The epoll file description that this EpollEventInterest is registered under.
75+
/// This is weak to avoid cycles, but an upgrade is always guaranteed to succeed
76+
/// because only the `Epoll` holds a strong ref to a `EpollEventInterest`.
7977
weak_epfd: WeakFileDescriptionRef<Epoll>,
8078
}
8179

@@ -142,12 +140,6 @@ impl EpollReadyEvents {
142140
}
143141
}
144142

145-
impl Epoll {
146-
fn get_ready_list(&self) -> Rc<ReadyList> {
147-
Rc::clone(&self.ready_list)
148-
}
149-
}
150-
151143
impl FileDescription for Epoll {
152144
fn name(&self) -> &'static str {
153145
"epoll"
@@ -279,12 +271,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
279271
let Some(epfd) = this.machine.fds.get(epfd_value) else {
280272
return this.set_last_error_and_return_i32(LibcError("EBADF"));
281273
};
282-
let epoll_file_description = epfd
274+
let epfd = epfd
283275
.downcast::<Epoll>()
284276
.ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?;
285277

286-
let mut interest_list = epoll_file_description.interest_list.borrow_mut();
287-
let ready_list = &epoll_file_description.ready_list;
278+
let mut interest_list = epfd.interest_list.borrow_mut();
288279

289280
let Some(fd_ref) = this.machine.fds.get(fd) else {
290281
return this.set_last_error_and_return_i32(LibcError("EBADF"));
@@ -345,30 +336,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
345336
}
346337
}
347338

348-
// Create an epoll_interest.
349-
let interest = Rc::new(RefCell::new(EpollEventInterest {
350-
fd_num: fd,
351-
events,
352-
data,
353-
ready_list: Rc::clone(ready_list),
354-
weak_epfd: FileDescriptionRef::downgrade(&epoll_file_description),
355-
}));
356-
357339
if op == epoll_ctl_add {
340+
// Create an epoll_interest.
341+
let interest = Rc::new(RefCell::new(EpollEventInterest {
342+
fd_num: fd,
343+
events,
344+
data,
345+
weak_epfd: FileDescriptionRef::downgrade(&epfd),
346+
}));
347+
// Notification will be returned for current epfd if there is event in the file
348+
// descriptor we registered.
349+
check_and_update_one_event_interest(&fd_ref, &interest, id, this)?;
350+
358351
// Insert an epoll_interest to global epoll_interest list.
359352
this.machine.epoll_interests.insert_epoll_interest(id, Rc::downgrade(&interest));
360-
interest_list.insert(epoll_key, Rc::clone(&interest));
353+
interest_list.insert(epoll_key, interest);
361354
} else {
362-
// Directly modify the epoll_interest so the global epoll_event_interest table
363-
// will be updated too.
364-
let mut epoll_interest = interest_list.get_mut(&epoll_key).unwrap().borrow_mut();
365-
epoll_interest.events = events;
366-
epoll_interest.data = data;
355+
// Modify the existing interest.
356+
let epoll_interest = interest_list.get_mut(&epoll_key).unwrap();
357+
{
358+
let mut epoll_interest = epoll_interest.borrow_mut();
359+
epoll_interest.events = events;
360+
epoll_interest.data = data;
361+
}
362+
// Updating an FD interest triggers events.
363+
check_and_update_one_event_interest(&fd_ref, epoll_interest, id, this)?;
367364
}
368365

369-
// Notification will be returned for current epfd if there is event in the file
370-
// descriptor we registered.
371-
check_and_update_one_event_interest(&fd_ref, &interest, id, this)?;
372366
interp_ok(Scalar::from_i32(0))
373367
} else if op == epoll_ctl_del {
374368
let epoll_key = (id, fd);
@@ -381,7 +375,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
381375
drop(epoll_interest);
382376

383377
// Remove related epoll_interest from ready list.
384-
ready_list.mapping.borrow_mut().remove(&epoll_key);
378+
epfd.ready_list.mapping.borrow_mut().remove(&epoll_key);
385379

386380
// Remove dangling EpollEventInterest from its global table.
387381
// .unwrap() below should succeed because the file description id must have registered
@@ -587,21 +581,22 @@ fn ready_list_next(
587581
/// notification to only one epoll instance.
588582
fn check_and_update_one_event_interest<'tcx>(
589583
fd_ref: &DynFileDescriptionRef,
590-
interest: &Rc<RefCell<EpollEventInterest>>,
584+
interest: &RefCell<EpollEventInterest>,
591585
id: FdId,
592586
ecx: &MiriInterpCx<'tcx>,
593587
) -> InterpResult<'tcx, bool> {
594588
// Get the bitmask of ready events for a file description.
595589
let ready_events_bitmask = fd_ref.as_unix().get_epoll_ready_events()?.get_event_bitmask(ecx);
596590
let epoll_event_interest = interest.borrow();
591+
let epfd = epoll_event_interest.weak_epfd.upgrade().unwrap();
597592
// This checks if any of the events specified in epoll_event_interest.events
598593
// match those in ready_events.
599594
let flags = epoll_event_interest.events & ready_events_bitmask;
600595
// If there is any event that we are interested in being specified as ready,
601596
// insert an epoll_return to the ready list.
602597
if flags != 0 {
603598
let epoll_key = (id, epoll_event_interest.fd_num);
604-
let ready_list = &mut epoll_event_interest.ready_list.mapping.borrow_mut();
599+
let mut ready_list = epfd.ready_list.mapping.borrow_mut();
605600
let mut event_instance = EpollEventInstance::new(flags, epoll_event_interest.data);
606601
// If we are tracking data races, remember the current clock so we can sync with it later.
607602
ecx.release_clock(|clock| {
@@ -623,9 +618,7 @@ fn return_ready_list<'tcx>(
623618
events: &MPlaceTy<'tcx>,
624619
ecx: &mut MiriInterpCx<'tcx>,
625620
) -> InterpResult<'tcx> {
626-
let ready_list = epfd.get_ready_list();
627-
628-
let mut ready_list = ready_list.mapping.borrow_mut();
621+
let mut ready_list = epfd.ready_list.mapping.borrow_mut();
629622
let mut num_of_events: i32 = 0;
630623
let mut array_iter = ecx.project_array_fields(events)?;
631624

0 commit comments

Comments
 (0)