11//! Linux `eventfd` implementation.
22use std:: io;
33use std:: io:: { Error , ErrorKind } ;
4+ use std:: mem;
45
56use rustc_target:: abi:: Endian ;
67
@@ -9,8 +10,8 @@ use crate::{concurrency::VClock, *};
910
1011use self :: shims:: unix:: fd:: FileDescriptor ;
1112
12- /// Minimum size of u8 array to hold u64 value .
13- const U64_MIN_ARRAY_SIZE : usize = 8 ;
13+ // We'll only do reads and writes in chunks of size u64 .
14+ const U64_ARRAY_SIZE : usize = mem :: size_of :: < u64 > ( ) ;
1415
1516/// Maximum value that the eventfd counter can hold.
1617const MAX_COUNTER : u64 = u64:: MAX - 1 ;
@@ -51,7 +52,7 @@ impl FileDescription for Event {
5152 ecx : & mut MiriInterpCx < ' tcx > ,
5253 ) -> InterpResult < ' tcx , io:: Result < usize > > {
5354 // Check the size of slice, and return error only if the size of the slice < 8.
54- let Some ( bytes) = bytes. first_chunk_mut :: < U64_MIN_ARRAY_SIZE > ( ) else {
55+ let Some ( bytes) = bytes. first_chunk_mut :: < U64_ARRAY_SIZE > ( ) else {
5556 return Ok ( Err ( Error :: from ( ErrorKind :: InvalidInput ) ) ) ;
5657 } ;
5758 // Block when counter == 0.
@@ -63,15 +64,15 @@ impl FileDescription for Event {
6364 throw_unsup_format ! ( "eventfd: blocking is unsupported" ) ;
6465 }
6566 } else {
66- // Prevent false alarm in data race detection when doing synchronisation via eventfd .
67+ // Synchronize with all prior `write` calls to this FD .
6768 ecx. acquire_clock ( & self . clock ) ;
6869 // Return the counter in the host endianness using the buffer provided by caller.
6970 * bytes = match ecx. tcx . sess . target . endian {
7071 Endian :: Little => self . counter . to_le_bytes ( ) ,
7172 Endian :: Big => self . counter . to_be_bytes ( ) ,
7273 } ;
7374 self . counter = 0 ;
74- return Ok ( Ok ( U64_MIN_ARRAY_SIZE ) ) ;
75+ return Ok ( Ok ( U64_ARRAY_SIZE ) ) ;
7576 }
7677 }
7778
@@ -94,7 +95,7 @@ impl FileDescription for Event {
9495 ecx : & mut MiriInterpCx < ' tcx > ,
9596 ) -> InterpResult < ' tcx , io:: Result < usize > > {
9697 // Check the size of slice, and return error only if the size of the slice < 8.
97- let Some ( bytes) = bytes. first_chunk :: < U64_MIN_ARRAY_SIZE > ( ) else {
98+ let Some ( bytes) = bytes. first_chunk :: < U64_ARRAY_SIZE > ( ) else {
9899 return Ok ( Err ( Error :: from ( ErrorKind :: InvalidInput ) ) ) ;
99100 } ;
100101 // Convert from bytes to int according to host endianness.
@@ -110,8 +111,10 @@ impl FileDescription for Event {
110111 // Else, block.
111112 match self . counter . checked_add ( num) {
112113 Some ( new_count @ 0 ..=MAX_COUNTER ) => {
113- // Prevent false alarm in data race detection when doing synchronisation via eventfd.
114- self . clock . join ( & ecx. release_clock ( ) . unwrap ( ) ) ;
114+ // Future `read` calls will synchronize with this write, so update the FD clock.
115+ if let Some ( clock) = & ecx. release_clock ( ) {
116+ self . clock . join ( clock) ;
117+ }
115118 self . counter = new_count;
116119 }
117120 None | Some ( u64:: MAX ) => {
@@ -123,7 +126,7 @@ impl FileDescription for Event {
123126 }
124127 }
125128 } ;
126- Ok ( Ok ( U64_MIN_ARRAY_SIZE ) )
129+ Ok ( Ok ( U64_ARRAY_SIZE ) )
127130 }
128131}
129132
@@ -163,19 +166,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
163166 }
164167
165168 let mut is_nonblock = false ;
166- // Unload the flag that we support.
169+ // Unset the flag that we support.
167170 // After unloading, flags != 0 means other flags are used.
168171 if flags & efd_cloexec == efd_cloexec {
172+ // cloexec is ignored because Miri does not support exec.
169173 flags &= !efd_cloexec;
170174 }
171175 if flags & efd_nonblock == efd_nonblock {
172176 flags &= !efd_nonblock;
173177 is_nonblock = true ;
174178 }
175179 if flags != 0 {
176- let einval = this. eval_libc ( "EINVAL" ) ;
177- this. set_last_error ( einval) ?;
178- return Ok ( Scalar :: from_i32 ( -1 ) ) ;
180+ throw_unsup_format ! ( "eventfd: encountered unknown unsupported flags {:#x}" , flags) ;
179181 }
180182
181183 let fd = this. machine . fds . insert_fd ( FileDescriptor :: new ( Event {
0 commit comments