Skip to content

Commit 1729042

Browse files
committed
make ecx.check_and_update_readiness a truly private helper function
1 parent 17b58bf commit 1729042

File tree

5 files changed

+74
-85
lines changed

5 files changed

+74
-85
lines changed

src/shims/unix/fd.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub trait FileDescription: std::fmt::Debug + Any {
2828
/// Reads as much as possible into the given buffer, and returns the number of bytes read.
2929
fn read<'tcx>(
3030
&self,
31+
_self_ref: &FileDescriptionRef,
3132
_communicate_allowed: bool,
32-
_fd_id: FdId,
3333
_bytes: &mut [u8],
3434
_ecx: &mut MiriInterpCx<'tcx>,
3535
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -39,8 +39,8 @@ pub trait FileDescription: std::fmt::Debug + Any {
3939
/// Writes as much as possible from the given buffer, and returns the number of bytes written.
4040
fn write<'tcx>(
4141
&self,
42+
_self_ref: &FileDescriptionRef,
4243
_communicate_allowed: bool,
43-
_fd_id: FdId,
4444
_bytes: &[u8],
4545
_ecx: &mut MiriInterpCx<'tcx>,
4646
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -123,8 +123,8 @@ impl FileDescription for io::Stdin {
123123

124124
fn read<'tcx>(
125125
&self,
126+
_self_ref: &FileDescriptionRef,
126127
communicate_allowed: bool,
127-
_fd_id: FdId,
128128
bytes: &mut [u8],
129129
_ecx: &mut MiriInterpCx<'tcx>,
130130
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -147,8 +147,8 @@ impl FileDescription for io::Stdout {
147147

148148
fn write<'tcx>(
149149
&self,
150+
_self_ref: &FileDescriptionRef,
150151
_communicate_allowed: bool,
151-
_fd_id: FdId,
152152
bytes: &[u8],
153153
_ecx: &mut MiriInterpCx<'tcx>,
154154
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -176,8 +176,8 @@ impl FileDescription for io::Stderr {
176176

177177
fn write<'tcx>(
178178
&self,
179+
_self_ref: &FileDescriptionRef,
179180
_communicate_allowed: bool,
180-
_fd_id: FdId,
181181
bytes: &[u8],
182182
_ecx: &mut MiriInterpCx<'tcx>,
183183
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -202,8 +202,8 @@ impl FileDescription for NullOutput {
202202

203203
fn write<'tcx>(
204204
&self,
205+
_self_ref: &FileDescriptionRef,
205206
_communicate_allowed: bool,
206-
_fd_id: FdId,
207207
bytes: &[u8],
208208
_ecx: &mut MiriInterpCx<'tcx>,
209209
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -261,16 +261,6 @@ impl FileDescriptionRef {
261261
pub fn get_id(&self) -> FdId {
262262
self.0.id
263263
}
264-
265-
/// Function used to retrieve the readiness events of a file description and insert
266-
/// an `EpollEventInstance` into the ready list if the file description is ready.
267-
pub(crate) fn check_and_update_readiness<'tcx>(
268-
&self,
269-
ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
270-
) -> InterpResult<'tcx, ()> {
271-
use crate::shims::unix::linux::epoll::EvalContextExt;
272-
ecx.check_and_update_readiness(self.get_id(), || self.get_epoll_ready_events())
273-
}
274264
}
275265

276266
/// Holds a weak reference to the actual file description.
@@ -567,7 +557,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
567557
// `usize::MAX` because it is bounded by the host's `isize`.
568558
let mut bytes = vec![0; usize::try_from(count).unwrap()];
569559
let result = match offset {
570-
None => fd.read(communicate, fd.get_id(), &mut bytes, this),
560+
None => fd.read(&fd, communicate, &mut bytes, this),
571561
Some(offset) => {
572562
let Ok(offset) = u64::try_from(offset) else {
573563
let einval = this.eval_libc("EINVAL");
@@ -625,7 +615,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
625615
};
626616

627617
let result = match offset {
628-
None => fd.write(communicate, fd.get_id(), &bytes, this),
618+
None => fd.write(&fd, communicate, &bytes, this),
629619
Some(offset) => {
630620
let Ok(offset) = u64::try_from(offset) else {
631621
let einval = this.eval_libc("EINVAL");

src/shims/unix/fs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashMap;
1212
use rustc_target::abi::Size;
1313

1414
use crate::shims::os_str::bytes_to_os_str;
15-
use crate::shims::unix::fd::FdId;
15+
use crate::shims::unix::fd::FileDescriptionRef;
1616
use crate::shims::unix::*;
1717
use crate::*;
1818
use shims::time::system_time_to_duration;
@@ -32,8 +32,8 @@ impl FileDescription for FileHandle {
3232

3333
fn read<'tcx>(
3434
&self,
35+
_self_ref: &FileDescriptionRef,
3536
communicate_allowed: bool,
36-
_fd_id: FdId,
3737
bytes: &mut [u8],
3838
_ecx: &mut MiriInterpCx<'tcx>,
3939
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -43,8 +43,8 @@ impl FileDescription for FileHandle {
4343

4444
fn write<'tcx>(
4545
&self,
46+
_self_ref: &FileDescriptionRef,
4647
communicate_allowed: bool,
47-
_fd_id: FdId,
4848
bytes: &[u8],
4949
_ecx: &mut MiriInterpCx<'tcx>,
5050
) -> InterpResult<'tcx, io::Result<usize>> {

src/shims/unix/linux/epoll.rs

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
33
use std::io;
44
use std::rc::{Rc, Weak};
55

6-
use crate::shims::unix::fd::FdId;
6+
use crate::shims::unix::fd::{FdId, FileDescriptionRef};
77
use crate::shims::unix::*;
88
use crate::*;
99

@@ -153,6 +153,60 @@ impl EpollInterestTable {
153153
}
154154
}
155155

156+
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
157+
trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
158+
/// For a specific unique file descriptor id, get its ready events and update
159+
/// the corresponding ready list. This function is called whenever a file description
160+
/// is registered with epoll, or when read, write, or close operations are performed,
161+
/// regardless of any changes in readiness.
162+
///
163+
/// This is an internal helper function and is typically not meant to be used directly.
164+
/// `FileDescriptionRef::check_and_update_readiness` should be preferred.
165+
fn check_and_update_readiness(
166+
&self,
167+
id: FdId,
168+
get_ready_events: impl FnOnce() -> InterpResult<'tcx, EpollReadyEvents>,
169+
) -> InterpResult<'tcx, ()> {
170+
let this = self.eval_context_ref();
171+
// Get a list of EpollEventInterest that is associated to a specific file description.
172+
if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) {
173+
let epoll_ready_events = get_ready_events()?;
174+
// Get the bitmask of ready events.
175+
let ready_events = epoll_ready_events.get_event_bitmask(this);
176+
177+
for weak_epoll_interest in epoll_interests {
178+
if let Some(epoll_interest) = weak_epoll_interest.upgrade() {
179+
// This checks if any of the events specified in epoll_event_interest.events
180+
// match those in ready_events.
181+
let epoll_event_interest = epoll_interest.borrow();
182+
let flags = epoll_event_interest.events & ready_events;
183+
// If there is any event that we are interested in being specified as ready,
184+
// insert an epoll_return to the ready list.
185+
if flags != 0 {
186+
let epoll_key = (id, epoll_event_interest.file_descriptor);
187+
let ready_list = &mut epoll_event_interest.ready_list.borrow_mut();
188+
let event_instance =
189+
EpollEventInstance::new(flags, epoll_event_interest.data);
190+
ready_list.insert(epoll_key, event_instance);
191+
}
192+
}
193+
}
194+
}
195+
Ok(())
196+
}
197+
}
198+
199+
impl FileDescriptionRef {
200+
/// Function used to retrieve the readiness events of a file description and insert
201+
/// an `EpollEventInstance` into the ready list if the file description is ready.
202+
pub(crate) fn check_and_update_readiness<'tcx>(
203+
&self,
204+
ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
205+
) -> InterpResult<'tcx, ()> {
206+
ecx.check_and_update_readiness(self.get_id(), || self.get_epoll_ready_events())
207+
}
208+
}
209+
156210
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
157211
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
158212
/// This function returns a file descriptor referring to the new `Epoll` instance. This file
@@ -431,44 +485,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
431485
}
432486
Ok(Scalar::from_i32(num_of_events))
433487
}
434-
435-
/// For a specific unique file descriptor id, get its ready events and update
436-
/// the corresponding ready list. This function is called whenever a file description
437-
/// is registered with epoll, or when read, write, or close operations are performed,
438-
/// regardless of any changes in readiness.
439-
///
440-
/// This is an internal helper function and is typically not meant to be used directly.
441-
/// In most cases, `FileDescriptionRef::check_and_update_readiness` should be preferred.
442-
fn check_and_update_readiness(
443-
&self,
444-
id: FdId,
445-
get_ready_events: impl FnOnce() -> InterpResult<'tcx, EpollReadyEvents>,
446-
) -> InterpResult<'tcx, ()> {
447-
let this = self.eval_context_ref();
448-
// Get a list of EpollEventInterest that is associated to a specific file description.
449-
if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) {
450-
let epoll_ready_events = get_ready_events()?;
451-
// Get the bitmask of ready events.
452-
let ready_events = epoll_ready_events.get_event_bitmask(this);
453-
454-
for weak_epoll_interest in epoll_interests {
455-
if let Some(epoll_interest) = weak_epoll_interest.upgrade() {
456-
// This checks if any of the events specified in epoll_event_interest.events
457-
// match those in ready_events.
458-
let epoll_event_interest = epoll_interest.borrow();
459-
let flags = epoll_event_interest.events & ready_events;
460-
// If there is any event that we are interested in being specified as ready,
461-
// insert an epoll_return to the ready list.
462-
if flags != 0 {
463-
let epoll_key = (id, epoll_event_interest.file_descriptor);
464-
let ready_list = &mut epoll_event_interest.ready_list.borrow_mut();
465-
let event_instance =
466-
EpollEventInstance::new(flags, epoll_event_interest.data);
467-
ready_list.insert(epoll_key, event_instance);
468-
}
469-
}
470-
}
471-
}
472-
Ok(())
473-
}
474488
}

src/shims/unix/linux/eventfd.rs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use std::io;
44
use std::io::{Error, ErrorKind};
55
use std::mem;
66

7-
use fd::FdId;
87
use rustc_target::abi::Endian;
98

9+
use crate::shims::unix::fd::FileDescriptionRef;
1010
use crate::shims::unix::linux::epoll::EpollReadyEvents;
1111
use crate::shims::unix::*;
1212
use crate::{concurrency::VClock, *};
@@ -60,8 +60,8 @@ impl FileDescription for Event {
6060
/// Read the counter in the buffer and return the counter if succeeded.
6161
fn read<'tcx>(
6262
&self,
63+
self_ref: &FileDescriptionRef,
6364
_communicate_allowed: bool,
64-
fd_id: FdId,
6565
bytes: &mut [u8],
6666
ecx: &mut MiriInterpCx<'tcx>,
6767
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -89,16 +89,8 @@ impl FileDescription for Event {
8989
self.counter.set(0);
9090
// When any of the event happened, we check and update the status of all supported event
9191
// types for current file description.
92+
self_ref.check_and_update_readiness(ecx)?;
9293

93-
// We have to use our own FdID in contrast to every other file descriptor out there, because
94-
// we are updating ourselves when writing and reading. Technically `Event` is like socketpair, but
95-
// it does not create two separate file descriptors. Thus we can't re-borrow ourselves via
96-
// `FileDescriptionRef::check_and_update_readiness` while already being mutably borrowed for read/write.
97-
crate::shims::unix::linux::epoll::EvalContextExt::check_and_update_readiness(
98-
ecx,
99-
fd_id,
100-
|| self.get_epoll_ready_events(),
101-
)?;
10294
return Ok(Ok(U64_ARRAY_SIZE));
10395
}
10496
}
@@ -117,8 +109,8 @@ impl FileDescription for Event {
117109
/// made to write the value 0xffffffffffffffff.
118110
fn write<'tcx>(
119111
&self,
112+
self_ref: &FileDescriptionRef,
120113
_communicate_allowed: bool,
121-
fd_id: FdId,
122114
bytes: &[u8],
123115
ecx: &mut MiriInterpCx<'tcx>,
124116
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -156,15 +148,8 @@ impl FileDescription for Event {
156148
};
157149
// When any of the event happened, we check and update the status of all supported event
158150
// types for current file description.
151+
self_ref.check_and_update_readiness(ecx)?;
159152

160-
// Just like read() above, we use this internal method to not get the second borrow of the
161-
// RefCell of this FileDescription. This is a special case, we should only use
162-
// FileDescriptionRef::check_and_update_readiness in normal case.
163-
crate::shims::unix::linux::epoll::EvalContextExt::check_and_update_readiness(
164-
ecx,
165-
fd_id,
166-
|| self.get_epoll_ready_events(),
167-
)?;
168153
Ok(Ok(U64_ARRAY_SIZE))
169154
}
170155
}

src/shims/unix/socket.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::VecDeque;
33
use std::io;
44
use std::io::{Error, ErrorKind, Read};
55

6-
use crate::shims::unix::fd::{FdId, WeakFileDescriptionRef};
6+
use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef};
77
use crate::shims::unix::linux::epoll::EpollReadyEvents;
88
use crate::shims::unix::*;
99
use crate::{concurrency::VClock, *};
@@ -94,8 +94,8 @@ impl FileDescription for SocketPair {
9494

9595
fn read<'tcx>(
9696
&self,
97+
_self_ref: &FileDescriptionRef,
9798
_communicate_allowed: bool,
98-
_fd_id: FdId,
9999
bytes: &mut [u8],
100100
ecx: &mut MiriInterpCx<'tcx>,
101101
) -> InterpResult<'tcx, io::Result<usize>> {
@@ -156,8 +156,8 @@ impl FileDescription for SocketPair {
156156

157157
fn write<'tcx>(
158158
&self,
159+
_self_ref: &FileDescriptionRef,
159160
_communicate_allowed: bool,
160-
_fd_id: FdId,
161161
bytes: &[u8],
162162
ecx: &mut MiriInterpCx<'tcx>,
163163
) -> InterpResult<'tcx, io::Result<usize>> {

0 commit comments

Comments
 (0)