2
2
use std:: cell:: { Cell , RefCell } ;
3
3
use std:: io;
4
4
use std:: io:: { Error , ErrorKind } ;
5
- use std:: mem;
6
5
7
6
use crate :: shims:: unix:: fd:: FileDescriptionRef ;
8
7
use crate :: shims:: unix:: linux:: epoll:: { EpollReadyEvents , EvalContextExt as _} ;
9
8
use crate :: shims:: unix:: * ;
10
9
use crate :: { concurrency:: VClock , * } ;
11
10
12
- // We'll only do reads and writes in chunks of size u64.
13
- const U64_ARRAY_SIZE : usize = mem:: size_of :: < u64 > ( ) ;
14
-
15
11
/// Maximum value that the eventfd counter can hold.
16
12
const MAX_COUNTER : u64 = u64:: MAX - 1 ;
17
13
@@ -65,35 +61,45 @@ impl FileDescription for Event {
65
61
dest : & MPlaceTy < ' tcx > ,
66
62
ecx : & mut MiriInterpCx < ' tcx > ,
67
63
) -> InterpResult < ' tcx > {
68
- // eventfd read at the size of u64.
69
- let buf_place = ecx. ptr_to_mplace_unaligned ( ptr , ecx . machine . layouts . u64 ) ;
64
+ // We're treating the buffer as a ` u64` .
65
+ let ty = ecx. machine . layouts . u64 ;
70
66
// Check the size of slice, and return error only if the size of the slice < 8.
71
- if len < U64_ARRAY_SIZE {
72
- let result = Err ( Error :: from ( ErrorKind :: InvalidInput ) ) ;
73
- return return_read_bytes_and_count_ev ( & buf_place, None , result, dest, ecx) ;
67
+ if len < ty. size . bytes_usize ( ) {
68
+ ecx. set_last_error_from_io_error ( Error :: from ( ErrorKind :: InvalidInput ) ) ?;
69
+ ecx. write_int ( -1 , dest) ?;
70
+ return Ok ( ( ) ) ;
74
71
}
75
72
73
+ // eventfd read at the size of u64.
74
+ let buf_place = ecx. ptr_to_mplace_unaligned ( ptr, ty) ;
75
+
76
76
// Block when counter == 0.
77
77
let counter = self . counter . get ( ) ;
78
78
if counter == 0 {
79
79
if self . is_nonblock {
80
- let result = Err ( Error :: from ( ErrorKind :: WouldBlock ) ) ;
81
- return return_read_bytes_and_count_ev ( & buf_place, None , result, dest, ecx) ;
82
- } else {
83
- //FIXME: blocking is not supported
84
- throw_unsup_format ! ( "eventfd: blocking is unsupported" ) ;
80
+ ecx. set_last_error_from_io_error ( Error :: from ( ErrorKind :: WouldBlock ) ) ?;
81
+ ecx. write_int ( -1 , dest) ?;
82
+ return Ok ( ( ) ) ;
85
83
}
84
+
85
+ throw_unsup_format ! ( "eventfd: blocking is unsupported" ) ;
86
86
} else {
87
87
// Synchronize with all prior `write` calls to this FD.
88
88
ecx. acquire_clock ( & self . clock . borrow ( ) ) ;
89
- let result = Ok ( U64_ARRAY_SIZE ) ;
89
+
90
+ // Give old counter value to userspace, and set counter value to 0.
91
+ ecx. write_int ( counter, & buf_place) ?;
90
92
self . counter . set ( 0 ) ;
93
+
91
94
// When any of the event happened, we check and update the status of all supported event
92
95
// types for current file description.
93
96
ecx. check_and_update_readiness ( self_ref) ?;
94
97
95
- return_read_bytes_and_count_ev ( & buf_place, Some ( counter) , result, dest, ecx)
98
+ // Tell userspace how many bytes we wrote.
99
+ ecx. write_int ( buf_place. layout . size . bytes ( ) , dest) ?;
96
100
}
101
+
102
+ Ok ( ( ) )
97
103
}
98
104
99
105
/// A write call adds the 8-byte integer value supplied in
@@ -117,14 +123,16 @@ impl FileDescription for Event {
117
123
dest : & MPlaceTy < ' tcx > ,
118
124
ecx : & mut MiriInterpCx < ' tcx > ,
119
125
) -> InterpResult < ' tcx > {
126
+ // We're treating the buffer as a `u64`.
127
+ let ty = ecx. machine . layouts . u64 ;
120
128
// Check the size of slice, and return error only if the size of the slice < 8.
121
- if len < U64_ARRAY_SIZE {
129
+ if len < ty . layout . size . bytes_usize ( ) {
122
130
let result = Err ( Error :: from ( ErrorKind :: InvalidInput ) ) ;
123
131
return ecx. return_written_byte_count_or_error ( result, dest) ;
124
132
}
125
133
126
134
// Read the user supplied value from the pointer.
127
- let buf_place = ecx. ptr_to_mplace_unaligned ( ptr, ecx . machine . layouts . u64 ) ;
135
+ let buf_place = ecx. ptr_to_mplace_unaligned ( ptr, ty ) ;
128
136
let num = ecx. read_scalar ( & buf_place) ?. to_u64 ( ) ?;
129
137
130
138
// u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1.
@@ -142,22 +150,20 @@ impl FileDescription for Event {
142
150
}
143
151
self . counter . set ( new_count) ;
144
152
}
145
- None | Some ( u64:: MAX ) => {
153
+ None | Some ( u64:: MAX ) =>
146
154
if self . is_nonblock {
147
155
let result = Err ( Error :: from ( ErrorKind :: WouldBlock ) ) ;
148
156
return ecx. return_written_byte_count_or_error ( result, dest) ;
149
157
} else {
150
- //FIXME: blocking is not supported
151
158
throw_unsup_format ! ( "eventfd: blocking is unsupported" ) ;
152
- }
153
- }
159
+ } ,
154
160
} ;
155
161
// When any of the event happened, we check and update the status of all supported event
156
162
// types for current file description.
157
163
ecx. check_and_update_readiness ( self_ref) ?;
158
164
159
- let result = Ok ( U64_ARRAY_SIZE ) ;
160
- ecx. return_written_byte_count_or_error ( result , dest)
165
+ // Return how many bytes we read.
166
+ ecx. write_int ( buf_place . layout . size . bytes ( ) , dest)
161
167
}
162
168
}
163
169
@@ -222,28 +228,3 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
222
228
Ok ( Scalar :: from_i32 ( fd_value) )
223
229
}
224
230
}
225
-
226
- /// This function either writes to the user supplied buffer and to dest place, or sets the
227
- /// last libc error and writes -1 to dest. This is only used by eventfd.
228
- fn return_read_bytes_and_count_ev < ' tcx > (
229
- buf_place : & MPlaceTy < ' tcx > ,
230
- read_val : Option < u64 > ,
231
- result : io:: Result < usize > ,
232
- dest : & MPlaceTy < ' tcx > ,
233
- ecx : & mut MiriInterpCx < ' tcx > ,
234
- ) -> InterpResult < ' tcx > {
235
- match result. map ( |c| i64:: try_from ( c) . unwrap ( ) ) {
236
- Ok ( read_bytes) => {
237
- // Write to the user supplied buffer.
238
- ecx. write_int ( read_val. unwrap ( ) , buf_place) ?;
239
- // Write to the function return value place.
240
- ecx. write_int ( read_bytes, dest) ?;
241
- return Ok ( ( ) ) ;
242
- }
243
- Err ( e) => {
244
- ecx. set_last_error_from_io_error ( e) ?;
245
- ecx. write_int ( -1 , dest) ?;
246
- return Ok ( ( ) ) ;
247
- }
248
- }
249
- }
0 commit comments