simplify Linux futex impl a bit
This commit is contained in:
parent
3f6fc1fb5a
commit
8f99d011f2
@ -1,7 +1,7 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::concurrency::thread::{MachineCallback, Time};
|
||||
use crate::*;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
use std::time::SystemTime;
|
||||
|
||||
/// Implementation of the SYS_futex syscall.
|
||||
/// `args` is the arguments *after* the syscall number.
|
||||
@ -28,13 +28,14 @@ pub fn futex<'tcx>(
|
||||
// The first three arguments (after the syscall number itself) are the same to all futex operations:
|
||||
// (int *addr, int op, int val).
|
||||
// We checked above that these definitely exist.
|
||||
let addr = this.read_immediate(&args[0])?;
|
||||
let addr = this.read_pointer(&args[0])?;
|
||||
let op = this.read_scalar(&args[1])?.to_i32()?;
|
||||
let val = this.read_scalar(&args[2])?.to_i32()?;
|
||||
|
||||
let thread = this.get_active_thread();
|
||||
let addr_scalar = addr.to_scalar();
|
||||
let addr_usize = addr_scalar.to_machine_usize(this)?;
|
||||
// This is a vararg function so we have to bring our own type for this pointer.
|
||||
let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
|
||||
let addr_usize = addr.ptr.addr().bytes();
|
||||
|
||||
let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
|
||||
let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
|
||||
@ -117,15 +118,6 @@ pub fn futex<'tcx>(
|
||||
}
|
||||
})
|
||||
};
|
||||
// Check the pointer for alignment and validity.
|
||||
// The API requires `addr` to be a 4-byte aligned pointer, and will
|
||||
// use the 4 bytes at the given address as an (atomic) i32.
|
||||
this.check_ptr_access_align(
|
||||
addr_scalar.to_pointer(this)?,
|
||||
Size::from_bytes(4),
|
||||
Align::from_bytes(4).unwrap(),
|
||||
CheckInAllocMsg::MemoryAccessTest,
|
||||
)?;
|
||||
// There may be a concurrent thread changing the value of addr
|
||||
// and then invoking the FUTEX_WAKE syscall. It is critical that the
|
||||
// effects of this and the other thread are correctly observed,
|
||||
@ -172,14 +164,7 @@ pub fn futex<'tcx>(
|
||||
this.atomic_fence(AtomicFenceOrd::SeqCst)?;
|
||||
// Read an `i32` through the pointer, regardless of any wrapper types.
|
||||
// It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`.
|
||||
let futex_val = this
|
||||
.read_scalar_at_offset_atomic(
|
||||
&addr.into(),
|
||||
0,
|
||||
this.machine.layouts.i32,
|
||||
AtomicReadOrd::Relaxed,
|
||||
)?
|
||||
.to_i32()?;
|
||||
let futex_val = this.read_scalar_atomic(&addr, AtomicReadOrd::Relaxed)?.to_i32()?;
|
||||
if val == futex_val {
|
||||
// The value still matches, so we block the thread make it wait for FUTEX_WAKE.
|
||||
this.block_thread(thread);
|
||||
|
Loading…
x
Reference in New Issue
Block a user