mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
simplify eventfd handling a bit
This commit is contained in:
parent
ed24426824
commit
d70fd882ef
@ -2,16 +2,12 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::mem;
|
||||
|
||||
use crate::shims::unix::fd::FileDescriptionRef;
|
||||
use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _};
|
||||
use crate::shims::unix::*;
|
||||
use crate::{concurrency::VClock, *};
|
||||
|
||||
// We'll only do reads and writes in chunks of size u64.
|
||||
const U64_ARRAY_SIZE: usize = mem::size_of::<u64>();
|
||||
|
||||
/// Maximum value that the eventfd counter can hold.
|
||||
const MAX_COUNTER: u64 = u64::MAX - 1;
|
||||
|
||||
@ -65,35 +61,45 @@ impl FileDescription for Event {
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ecx: &mut MiriInterpCx<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// eventfd read at the size of u64.
|
||||
let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ecx.machine.layouts.u64);
|
||||
// We're treating the buffer as a `u64`.
|
||||
let ty = ecx.machine.layouts.u64;
|
||||
// Check the size of slice, and return error only if the size of the slice < 8.
|
||||
if len < U64_ARRAY_SIZE {
|
||||
let result = Err(Error::from(ErrorKind::InvalidInput));
|
||||
return return_read_bytes_and_count_ev(&buf_place, None, result, dest, ecx);
|
||||
if len < ty.size.bytes_usize() {
|
||||
ecx.set_last_error_from_io_error(Error::from(ErrorKind::InvalidInput))?;
|
||||
ecx.write_int(-1, dest)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// eventfd read at the size of u64.
|
||||
let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty);
|
||||
|
||||
// Block when counter == 0.
|
||||
let counter = self.counter.get();
|
||||
if counter == 0 {
|
||||
if self.is_nonblock {
|
||||
let result = Err(Error::from(ErrorKind::WouldBlock));
|
||||
return return_read_bytes_and_count_ev(&buf_place, None, result, dest, ecx);
|
||||
} else {
|
||||
//FIXME: blocking is not supported
|
||||
throw_unsup_format!("eventfd: blocking is unsupported");
|
||||
ecx.set_last_error_from_io_error(Error::from(ErrorKind::WouldBlock))?;
|
||||
ecx.write_int(-1, dest)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
throw_unsup_format!("eventfd: blocking is unsupported");
|
||||
} else {
|
||||
// Synchronize with all prior `write` calls to this FD.
|
||||
ecx.acquire_clock(&self.clock.borrow());
|
||||
let result = Ok(U64_ARRAY_SIZE);
|
||||
|
||||
// Give old counter value to userspace, and set counter value to 0.
|
||||
ecx.write_int(counter, &buf_place)?;
|
||||
self.counter.set(0);
|
||||
|
||||
// When any of the event happened, we check and update the status of all supported event
|
||||
// types for current file description.
|
||||
ecx.check_and_update_readiness(self_ref)?;
|
||||
|
||||
return_read_bytes_and_count_ev(&buf_place, Some(counter), result, dest, ecx)
|
||||
// Tell userspace how many bytes we wrote.
|
||||
ecx.write_int(buf_place.layout.size.bytes(), dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A write call adds the 8-byte integer value supplied in
|
||||
@ -117,14 +123,16 @@ impl FileDescription for Event {
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ecx: &mut MiriInterpCx<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// We're treating the buffer as a `u64`.
|
||||
let ty = ecx.machine.layouts.u64;
|
||||
// Check the size of slice, and return error only if the size of the slice < 8.
|
||||
if len < U64_ARRAY_SIZE {
|
||||
if len < ty.layout.size.bytes_usize() {
|
||||
let result = Err(Error::from(ErrorKind::InvalidInput));
|
||||
return ecx.return_written_byte_count_or_error(result, dest);
|
||||
}
|
||||
|
||||
// Read the user supplied value from the pointer.
|
||||
let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ecx.machine.layouts.u64);
|
||||
let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty);
|
||||
let num = ecx.read_scalar(&buf_place)?.to_u64()?;
|
||||
|
||||
// u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1.
|
||||
@ -142,22 +150,20 @@ impl FileDescription for Event {
|
||||
}
|
||||
self.counter.set(new_count);
|
||||
}
|
||||
None | Some(u64::MAX) => {
|
||||
None | Some(u64::MAX) =>
|
||||
if self.is_nonblock {
|
||||
let result = Err(Error::from(ErrorKind::WouldBlock));
|
||||
return ecx.return_written_byte_count_or_error(result, dest);
|
||||
} else {
|
||||
//FIXME: blocking is not supported
|
||||
throw_unsup_format!("eventfd: blocking is unsupported");
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
// When any of the event happened, we check and update the status of all supported event
|
||||
// types for current file description.
|
||||
ecx.check_and_update_readiness(self_ref)?;
|
||||
|
||||
let result = Ok(U64_ARRAY_SIZE);
|
||||
ecx.return_written_byte_count_or_error(result, dest)
|
||||
// Return how many bytes we read.
|
||||
ecx.write_int(buf_place.layout.size.bytes(), dest)
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,28 +228,3 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
Ok(Scalar::from_i32(fd_value))
|
||||
}
|
||||
}
|
||||
|
||||
/// This function either writes to the user supplied buffer and to dest place, or sets the
|
||||
/// last libc error and writes -1 to dest. This is only used by eventfd.
|
||||
fn return_read_bytes_and_count_ev<'tcx>(
|
||||
buf_place: &MPlaceTy<'tcx>,
|
||||
read_val: Option<u64>,
|
||||
result: io::Result<usize>,
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ecx: &mut MiriInterpCx<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
match result.map(|c| i64::try_from(c).unwrap()) {
|
||||
Ok(read_bytes) => {
|
||||
// Write to the user supplied buffer.
|
||||
ecx.write_int(read_val.unwrap(), buf_place)?;
|
||||
// Write to the function return value place.
|
||||
ecx.write_int(read_bytes, dest)?;
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
ecx.set_last_error_from_io_error(e)?;
|
||||
ecx.write_int(-1, dest)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user