@@ -9,7 +9,7 @@ struct LinuxFutex {
99/// Implementation of the SYS_futex syscall.
1010/// `args` is the arguments *including* the syscall number.
1111pub fn futex < ' tcx > (
12- this : & mut MiriInterpCx < ' tcx > ,
12+ ecx : & mut MiriInterpCx < ' tcx > ,
1313 args : & [ OpTy < ' tcx > ] ,
1414 dest : & MPlaceTy < ' tcx > ,
1515) -> InterpResult < ' tcx > {
@@ -26,19 +26,19 @@ pub fn futex<'tcx>(
2626 // The first three arguments (after the syscall number itself) are the same to all futex operations:
2727 // (int *addr, int op, int val).
2828 // We checked above that these definitely exist.
29- let addr = this . read_pointer ( addr) ?;
30- let op = this . read_scalar ( op) ?. to_i32 ( ) ?;
31- let val = this . read_scalar ( val) ?. to_i32 ( ) ?;
29+ let addr = ecx . read_pointer ( addr) ?;
30+ let op = ecx . read_scalar ( op) ?. to_i32 ( ) ?;
31+ let val = ecx . read_scalar ( val) ?. to_i32 ( ) ?;
3232
3333 // This is a vararg function so we have to bring our own type for this pointer.
34- let addr = this . ptr_to_mplace ( addr, this . machine . layouts . i32 ) ;
34+ let addr = ecx . ptr_to_mplace ( addr, ecx . machine . layouts . i32 ) ;
3535
36- let futex_private = this . eval_libc_i32 ( "FUTEX_PRIVATE_FLAG" ) ;
37- let futex_wait = this . eval_libc_i32 ( "FUTEX_WAIT" ) ;
38- let futex_wait_bitset = this . eval_libc_i32 ( "FUTEX_WAIT_BITSET" ) ;
39- let futex_wake = this . eval_libc_i32 ( "FUTEX_WAKE" ) ;
40- let futex_wake_bitset = this . eval_libc_i32 ( "FUTEX_WAKE_BITSET" ) ;
41- let futex_realtime = this . eval_libc_i32 ( "FUTEX_CLOCK_REALTIME" ) ;
36+ let futex_private = ecx . eval_libc_i32 ( "FUTEX_PRIVATE_FLAG" ) ;
37+ let futex_wait = ecx . eval_libc_i32 ( "FUTEX_WAIT" ) ;
38+ let futex_wait_bitset = ecx . eval_libc_i32 ( "FUTEX_WAIT_BITSET" ) ;
39+ let futex_wake = ecx . eval_libc_i32 ( "FUTEX_WAKE" ) ;
40+ let futex_wake_bitset = ecx . eval_libc_i32 ( "FUTEX_WAKE_BITSET" ) ;
41+ let futex_realtime = ecx . eval_libc_i32 ( "FUTEX_CLOCK_REALTIME" ) ;
4242
4343 // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
4444 // Miri doesn't support that anyway, so we ignore that flag.
@@ -57,31 +57,31 @@ pub fn futex<'tcx>(
5757 let ( timeout, bitset) = if wait_bitset {
5858 let [ _, _, _, _, timeout, uaddr2, bitset] =
5959 check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`" , args) ?;
60- let _timeout = this . read_pointer ( timeout) ?;
61- let _uaddr2 = this . read_pointer ( uaddr2) ?;
62- ( timeout, this . read_scalar ( bitset) ?. to_u32 ( ) ?)
60+ let _timeout = ecx . read_pointer ( timeout) ?;
61+ let _uaddr2 = ecx . read_pointer ( uaddr2) ?;
62+ ( timeout, ecx . read_scalar ( bitset) ?. to_u32 ( ) ?)
6363 } else {
6464 let [ _, _, _, _, timeout] =
6565 check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAIT, ...)`" , args) ?;
6666 ( timeout, u32:: MAX )
6767 } ;
6868
6969 if bitset == 0 {
70- return this . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
70+ return ecx . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
7171 }
7272
73- let timeout = this . deref_pointer_as ( timeout, this . libc_ty_layout ( "timespec" ) ) ?;
74- let timeout = if this . ptr_is_null ( timeout. ptr ( ) ) ? {
73+ let timeout = ecx . deref_pointer_as ( timeout, ecx . libc_ty_layout ( "timespec" ) ) ?;
74+ let timeout = if ecx . ptr_is_null ( timeout. ptr ( ) ) ? {
7575 None
7676 } else {
77- let duration = match this . read_timespec ( & timeout) ? {
77+ let duration = match ecx . read_timespec ( & timeout) ? {
7878 Some ( duration) => duration,
7979 None => {
80- return this . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
80+ return ecx . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
8181 }
8282 } ;
8383 let timeout_clock = if op & futex_realtime == futex_realtime {
84- this . check_no_isolation (
84+ ecx . check_no_isolation (
8585 "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`" ,
8686 ) ?;
8787 TimeoutClock :: RealTime
@@ -139,36 +139,36 @@ pub fn futex<'tcx>(
139139 //
140140 // Thankfully, preemptions cannot happen inside a Miri shim, so we do not need to
141141 // do anything special to guarantee fence-load-comparison atomicity.
142- this . atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
142+ ecx . atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
143143 // Read an `i32` through the pointer, regardless of any wrapper types.
144144 // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
145145 // We do an acquire read -- it only seems reasonable that if we observe a value here, we
146146 // actually establish an ordering with that value.
147- let futex_val = this . read_scalar_atomic ( & addr, AtomicReadOrd :: Acquire ) ?. to_i32 ( ) ?;
147+ let futex_val = ecx . read_scalar_atomic ( & addr, AtomicReadOrd :: Acquire ) ?. to_i32 ( ) ?;
148148 if val == futex_val {
149149 // The value still matches, so we block the thread and make it wait for FUTEX_WAKE.
150150
151151 // This cannot fail since we already did an atomic acquire read on that pointer.
152152 // Acquire reads are only allowed on mutable memory.
153- let futex_ref = this
153+ let futex_ref = ecx
154154 . get_sync_or_init ( addr. ptr ( ) , |_| LinuxFutex { futex : Default :: default ( ) } )
155155 . unwrap ( )
156156 . futex
157157 . clone ( ) ;
158158
159- this . futex_wait (
159+ ecx . futex_wait (
160160 futex_ref,
161161 bitset,
162162 timeout,
163- Scalar :: from_target_isize ( 0 , this ) , // retval_succ
164- Scalar :: from_target_isize ( -1 , this ) , // retval_timeout
163+ Scalar :: from_target_isize ( 0 , ecx ) , // retval_succ
164+ Scalar :: from_target_isize ( -1 , ecx ) , // retval_timeout
165165 dest. clone ( ) ,
166166 LibcError ( "ETIMEDOUT" ) , // errno_timeout
167167 ) ;
168168 } else {
169169 // The futex value doesn't match the expected value, so we return failure
170170 // right away without sleeping: -1 and errno set to EAGAIN.
171- return this . set_last_error_and_return ( LibcError ( "EAGAIN" ) , dest) ;
171+ return ecx . set_last_error_and_return ( LibcError ( "EAGAIN" ) , dest) ;
172172 }
173173 }
174174 // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
@@ -179,42 +179,42 @@ pub fn futex<'tcx>(
179179 // Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up.
180180 op if op == futex_wake || op == futex_wake_bitset => {
181181 let Some ( futex_ref) =
182- this . get_sync_or_init ( addr. ptr ( ) , |_| LinuxFutex { futex : Default :: default ( ) } )
182+ ecx . get_sync_or_init ( addr. ptr ( ) , |_| LinuxFutex { futex : Default :: default ( ) } )
183183 else {
184184 // No AllocId, or no live allocation at that AllocId.
185185 // Return an error code. (That seems nicer than silently doing something non-intuitive.)
186186 // This means that if an address gets reused by a new allocation,
187187 // we'll use an independent futex queue for this... that seems acceptable.
188- return this . set_last_error_and_return ( LibcError ( "EFAULT" ) , dest) ;
188+ return ecx . set_last_error_and_return ( LibcError ( "EFAULT" ) , dest) ;
189189 } ;
190190 let futex_ref = futex_ref. futex . clone ( ) ;
191191
192192 let bitset = if op == futex_wake_bitset {
193193 let [ _, _, _, _, timeout, uaddr2, bitset] =
194194 check_min_arg_count ( "`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`" , args) ?;
195- let _timeout = this . read_pointer ( timeout) ?;
196- let _uaddr2 = this . read_pointer ( uaddr2) ?;
197- this . read_scalar ( bitset) ?. to_u32 ( ) ?
195+ let _timeout = ecx . read_pointer ( timeout) ?;
196+ let _uaddr2 = ecx . read_pointer ( uaddr2) ?;
197+ ecx . read_scalar ( bitset) ?. to_u32 ( ) ?
198198 } else {
199199 u32:: MAX
200200 } ;
201201 if bitset == 0 {
202- return this . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
202+ return ecx . set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
203203 }
204204 // Together with the SeqCst fence in futex_wait, this makes sure that futex_wait
205205 // will see the latest value on addr which could be changed by our caller
206206 // before doing the syscall.
207- this . atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
207+ ecx . atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
208208 let mut n = 0 ;
209209 #[ expect( clippy:: arithmetic_side_effects) ]
210210 for _ in 0 ..val {
211- if this . futex_wake ( & futex_ref, bitset) ? {
211+ if ecx . futex_wake ( & futex_ref, bitset) ? {
212212 n += 1 ;
213213 } else {
214214 break ;
215215 }
216216 }
217- this . write_scalar ( Scalar :: from_target_isize ( n, this ) , dest) ?;
217+ ecx . write_scalar ( Scalar :: from_target_isize ( n, ecx ) , dest) ?;
218218 }
219219 op => throw_unsup_format ! ( "Miri does not support `futex` syscall with op={}" , op) ,
220220 }
0 commit comments