@@ -7,6 +7,8 @@ use socketpair::SocketPair;
77
88use shims:: unix:: fs:: EvalContextExt as _;
99
10+ use std:: cell:: Cell ;
11+
1012pub mod epoll;
1113pub mod event;
1214pub mod socketpair;
@@ -101,6 +103,60 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
101103 }
102104 }
103105
106+ /// The `epoll_wait()` system call waits for events on the `Epoll`
107+ /// instance referred to by the file descriptor `epfd`. The buffer
108+ /// pointed to by `events` is used to return information from the ready
109+ /// list about file descriptors in the interest list that have some
110+ /// events available. Up to `maxevents` are returned by `epoll_wait()`.
111+ /// The `maxevents` argument must be greater than zero.
112+
113+ /// The `timeout` argument specifies the number of milliseconds that
114+ /// `epoll_wait()` will block. Time is measured against the
115+ /// CLOCK_MONOTONIC clock.
116+
117+ /// A call to `epoll_wait()` will block until either:
118+ /// • a file descriptor delivers an event;
119+ /// • the call is interrupted by a signal handler; or
120+ /// • the timeout expires.
121+
122+ /// Note that the timeout interval will be rounded up to the system
123+ /// clock granularity, and kernel scheduling delays mean that the
124+ /// blocking interval may overrun by a small amount. Specifying a
125+ /// timeout of -1 causes `epoll_wait()` to block indefinitely, while
126+ /// specifying a timeout equal to zero cause `epoll_wait()` to return
127+ /// immediately, even if no events are available.
128+ ///
129+ /// On success, `epoll_wait()` returns the number of file descriptors
130+ /// ready for the requested I/O, or zero if no file descriptor became
131+ /// ready during the requested timeout milliseconds. On failure,
132+ /// `epoll_wait()` returns -1 and errno is set to indicate the error.
133+ ///
134+ /// <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>
135+ fn epoll_wait (
136+ & mut self ,
137+ epfd : & OpTy < ' tcx , Provenance > ,
138+ events : & OpTy < ' tcx , Provenance > ,
139+ maxevents : & OpTy < ' tcx , Provenance > ,
140+ timeout : & OpTy < ' tcx , Provenance > ,
141+ ) -> InterpResult < ' tcx , Scalar < Provenance > > {
142+ let this = self . eval_context_mut ( ) ;
143+
144+ let epfd = this. read_scalar ( epfd) ?. to_i32 ( ) ?;
145+ let _events = this. read_scalar ( events) ?. to_pointer ( this) ?;
146+ let _maxevents = this. read_scalar ( maxevents) ?. to_i32 ( ) ?;
147+ let _timeout = this. read_scalar ( timeout) ?. to_i32 ( ) ?;
148+
149+ let numevents = 0 ;
150+ if let Some ( epfd) = this. machine . file_handler . handles . get_mut ( & epfd) {
151+ let _epfd = epfd. as_epoll_handle ( ) ?;
152+
153+ // FIXME return number of events ready when scheme for marking events ready exists
154+ Ok ( Scalar :: from_i32 ( numevents) )
155+ } else {
156+ Ok ( Scalar :: from_i32 ( this. handle_not_found ( ) ?) )
157+ }
158+ }
159+
104160 /// This function creates an `Event` that is used as an event wait/notify mechanism by
105161 /// user-space applications, and by the kernel to notify user-space applications of events.
106162 /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
@@ -142,7 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
142198 }
143199
144200 let fh = & mut this. machine . file_handler ;
145- let fd = fh. insert_fd ( Box :: new ( Event { val } ) ) ;
201+ let fd = fh. insert_fd ( Box :: new ( Event { val : Cell :: new ( val . into ( ) ) } ) ) ;
146202 Ok ( Scalar :: from_i32 ( fd) )
147203 }
148204
0 commit comments