1
+ use std:: time:: SystemTime ;
2
+
1
3
use crate :: concurrency:: thread:: { MachineCallback , Time } ;
2
4
use crate :: * ;
3
- use rustc_target:: abi:: { Align , Size } ;
4
- use std:: time:: SystemTime ;
5
5
6
6
/// Implementation of the SYS_futex syscall.
7
7
/// `args` is the arguments *after* the syscall number.
@@ -28,13 +28,14 @@ pub fn futex<'tcx>(
28
28
// The first three arguments (after the syscall number itself) are the same to all futex operations:
29
29
// (int *addr, int op, int val).
30
30
// We checked above that these definitely exist.
31
- let addr = this. read_immediate ( & args[ 0 ] ) ?;
31
+ let addr = this. read_pointer ( & args[ 0 ] ) ?;
32
32
let op = this. read_scalar ( & args[ 1 ] ) ?. to_i32 ( ) ?;
33
33
let val = this. read_scalar ( & args[ 2 ] ) ?. to_i32 ( ) ?;
34
34
35
35
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 ( ) ;
38
39
39
40
let futex_private = this. eval_libc_i32 ( "FUTEX_PRIVATE_FLAG" ) ?;
40
41
let futex_wait = this. eval_libc_i32 ( "FUTEX_WAIT" ) ?;
@@ -89,9 +90,11 @@ pub fn futex<'tcx>(
89
90
let timeout_time = if this. ptr_is_null ( timeout. ptr ) ? {
90
91
None
91
92
} 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
+ }
95
98
let duration = match this. read_timespec ( & timeout) ? {
96
99
Some ( duration) => duration,
97
100
None => {
@@ -117,15 +120,6 @@ pub fn futex<'tcx>(
117
120
}
118
121
} )
119
122
} ;
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
- ) ?;
129
123
// There may be a concurrent thread changing the value of addr
130
124
// and then invoking the FUTEX_WAKE syscall. It is critical that the
131
125
// effects of this and the other thread are correctly observed,
@@ -172,14 +166,7 @@ pub fn futex<'tcx>(
172
166
this. atomic_fence ( AtomicFenceOrd :: SeqCst ) ?;
173
167
// Read an `i32` through the pointer, regardless of any wrapper types.
174
168
// 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 ( ) ?;
183
170
if val == futex_val {
184
171
// The value still matches, so we block the thread make it wait for FUTEX_WAKE.
185
172
this. block_thread ( thread) ;
@@ -214,11 +201,10 @@ pub fn futex<'tcx>(
214
201
}
215
202
}
216
203
217
- let dest = dest. clone ( ) ;
218
204
this. register_timeout_callback (
219
205
thread,
220
206
timeout_time,
221
- Box :: new ( Callback { thread, addr_usize, dest } ) ,
207
+ Box :: new ( Callback { thread, addr_usize, dest : dest . clone ( ) } ) ,
222
208
) ;
223
209
}
224
210
} else {
0 commit comments