1+ use std:: time:: SystemTime ;
2+
13use crate :: concurrency:: thread:: { MachineCallback , Time } ;
24use crate :: * ;
3- use rustc_target:: abi:: { Align , Size } ;
4- use std:: time:: SystemTime ;
55
66/// Implementation of the SYS_futex syscall.
77/// `args` is the arguments *after* the syscall number.
@@ -28,13 +28,14 @@ pub fn futex<'tcx>(
2828 // The first three arguments (after the syscall number itself) are the same to all futex operations:
2929 // (int *addr, int op, int val).
3030 // We checked above that these definitely exist.
31- let addr = this. read_immediate ( & args[ 0 ] ) ?;
31+ let addr = this. read_pointer ( & args[ 0 ] ) ?;
3232 let op = this. read_scalar ( & args[ 1 ] ) ?. to_i32 ( ) ?;
3333 let val = this. read_scalar ( & args[ 2 ] ) ?. to_i32 ( ) ?;
3434
3535 let thread = this. get_active_thread ( ) ;
36- let addr_scalar = addr. to_scalar ( ) ;
37- let addr_usize = addr_scalar. to_machine_usize ( this) ?;
36+ // This is a vararg function so we have to bring our own type for this pointer.
37+ let addr = MPlaceTy :: from_aligned_ptr ( addr, this. machine . layouts . i32 ) ;
38+ let addr_usize = addr. ptr . addr ( ) . bytes ( ) ;
3839
3940 let futex_private = this. eval_libc_i32 ( "FUTEX_PRIVATE_FLAG" ) ?;
4041 let futex_wait = this. eval_libc_i32 ( "FUTEX_WAIT" ) ?;
@@ -89,9 +90,11 @@ pub fn futex<'tcx>(
8990 let timeout_time = if this. ptr_is_null ( timeout. ptr ) ? {
9091 None
9192 } else {
92- this. check_no_isolation (
93- "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout" ,
94- ) ?;
93+ if op & futex_realtime != 0 {
94+ this. check_no_isolation (
95+ "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`" ,
96+ ) ?;
97+ }
9598 let duration = match this. read_timespec ( & timeout) ? {
9699 Some ( duration) => duration,
97100 None => {
@@ -117,15 +120,6 @@ pub fn futex<'tcx>(
117120 }
118121 } )
119122 } ;
120- // Check the pointer for alignment and validity.
121- // The API requires `addr` to be a 4-byte aligned pointer, and will
122- // use the 4 bytes at the given address as an (atomic) i32.
123- this. check_ptr_access_align (
124- addr_scalar. to_pointer ( this) ?,
125- Size :: from_bytes ( 4 ) ,
126- Align :: from_bytes ( 4 ) . unwrap ( ) ,
127- CheckInAllocMsg :: MemoryAccessTest ,
128- ) ?;
129123 // There may be a concurrent thread changing the value of addr
130124 // and then invoking the FUTEX_WAKE syscall. It is critical that the
131125 // effects of this and the other thread are correctly observed,
@@ -172,14 +166,7 @@ pub fn futex<'tcx>(
172166 this. atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
173167 // Read an `i32` through the pointer, regardless of any wrapper types.
174168 // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
175- let futex_val = this
176- . read_scalar_at_offset_atomic (
177- & addr. into ( ) ,
178- 0 ,
179- this. machine . layouts . i32 ,
180- AtomicReadOrd :: Relaxed ,
181- ) ?
182- . to_i32 ( ) ?;
169+ let futex_val = this. read_scalar_atomic ( & addr, AtomicReadOrd :: Relaxed ) ?. to_i32 ( ) ?;
183170 if val == futex_val {
184171 // The value still matches, so we block the thread make it wait for FUTEX_WAKE.
185172 this. block_thread ( thread) ;
@@ -214,11 +201,10 @@ pub fn futex<'tcx>(
214201 }
215202 }
216203
217- let dest = dest. clone ( ) ;
218204 this. register_timeout_callback (
219205 thread,
220206 timeout_time,
221- Box :: new ( Callback { thread, addr_usize, dest } ) ,
207+ Box :: new ( Callback { thread, addr_usize, dest : dest . clone ( ) } ) ,
222208 ) ;
223209 }
224210 } else {
0 commit comments