Auto merge of #3444 - RalfJung:linux-epoll-eventfd-cleanup, r=RalfJung
shims/linux: move epoll and eventfd into their own respective files Also put the FD types into those files; they can then even be made private there.
This commit is contained in:
commit
1981895a97
@ -52,6 +52,8 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
|
|||||||
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
|
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
|
||||||
|
|
||||||
fn is_tty(&self, _communicate_allowed: bool) -> bool {
|
fn is_tty(&self, _communicate_allowed: bool) -> bool {
|
||||||
|
// Most FDs are not tty's and the consequence of a wrong `false` are minor,
|
||||||
|
// so we use a default impl here.
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,50 @@
|
|||||||
use std::cell::Cell;
|
use std::io;
|
||||||
|
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
use crate::shims::unix::*;
|
use crate::shims::unix::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use epoll::{Epoll, EpollEvent};
|
|
||||||
use event::Event;
|
|
||||||
|
|
||||||
pub mod epoll;
|
/// An `Epoll` file descriptor connects file handles and epoll events
|
||||||
pub mod event;
|
#[derive(Clone, Debug, Default)]
|
||||||
|
struct Epoll {
|
||||||
|
/// The file descriptors we are watching, and what we are watching for.
|
||||||
|
file_descriptors: FxHashMap<i32, EpollEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Epoll Events associate events with data.
|
||||||
|
/// These fields are currently unused by miri.
|
||||||
|
/// This matches the `epoll_event` struct defined
|
||||||
|
/// by the epoll_ctl man page. For more information
|
||||||
|
/// see the man page:
|
||||||
|
///
|
||||||
|
/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct EpollEvent {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
events: u32,
|
||||||
|
/// `Scalar<Provenance>` is used to represent the
|
||||||
|
/// `epoll_data` type union.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
data: Scalar<Provenance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileDescriptor for Epoll {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"epoll"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
|
||||||
|
Ok(Box::new(self.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close<'tcx>(
|
||||||
|
self: Box<Self>,
|
||||||
|
_communicate_allowed: bool,
|
||||||
|
) -> InterpResult<'tcx, io::Result<i32>> {
|
||||||
|
Ok(Ok(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
@ -156,49 +194,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
Ok(Scalar::from_i32(this.fd_not_found()?))
|
Ok(Scalar::from_i32(this.fd_not_found()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function creates an `Event` that is used as an event wait/notify mechanism by
|
|
||||||
/// user-space applications, and by the kernel to notify user-space applications of events.
|
|
||||||
/// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
|
|
||||||
/// with the value specified in the `initval` argument.
|
|
||||||
///
|
|
||||||
/// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`,
|
|
||||||
/// `select`, and `close` operations can be performed on the file descriptor. For more
|
|
||||||
/// information on these operations, see the man page linked below.
|
|
||||||
///
|
|
||||||
/// The `flags` are not currently implemented for eventfd.
|
|
||||||
/// The `flags` may be bitwise ORed to change the behavior of `eventfd`:
|
|
||||||
/// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
|
|
||||||
/// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description.
|
|
||||||
/// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
|
|
||||||
///
|
|
||||||
/// <https://linux.die.net/man/2/eventfd>
|
|
||||||
#[expect(clippy::needless_if)]
|
|
||||||
fn eventfd(
|
|
||||||
&mut self,
|
|
||||||
val: &OpTy<'tcx, Provenance>,
|
|
||||||
flags: &OpTy<'tcx, Provenance>,
|
|
||||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
|
||||||
let this = self.eval_context_mut();
|
|
||||||
|
|
||||||
let val = this.read_scalar(val)?.to_u32()?;
|
|
||||||
let flags = this.read_scalar(flags)?.to_i32()?;
|
|
||||||
|
|
||||||
let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC");
|
|
||||||
let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK");
|
|
||||||
let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE");
|
|
||||||
|
|
||||||
if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 {
|
|
||||||
throw_unsup_format!("{flags} is unsupported");
|
|
||||||
}
|
|
||||||
// FIXME handle the cloexec and nonblock flags
|
|
||||||
if flags & efd_cloexec == efd_cloexec {}
|
|
||||||
if flags & efd_nonblock == efd_nonblock {}
|
|
||||||
if flags & efd_semaphore == efd_semaphore {
|
|
||||||
throw_unsup_format!("EFD_SEMAPHORE is unsupported");
|
|
||||||
}
|
|
||||||
|
|
||||||
let fd = this.machine.fds.insert_fd(Box::new(Event { val: Cell::new(val.into()) }));
|
|
||||||
Ok(Scalar::from_i32(fd))
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
use crate::shims::unix::FileDescriptor;
|
//! Linux `eventfd` implementation.
|
||||||
|
//! Currently just a stub.
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
use rustc_const_eval::interpret::InterpResult;
|
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_target::abi::Endian;
|
use rustc_target::abi::Endian;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use crate::shims::unix::*;
|
||||||
use std::io;
|
use crate::*;
|
||||||
|
|
||||||
/// A kind of file descriptor created by `eventfd`.
|
/// A kind of file descriptor created by `eventfd`.
|
||||||
/// The `Event` type isn't currently written to by `eventfd`.
|
/// The `Event` type isn't currently written to by `eventfd`.
|
||||||
@ -15,10 +17,10 @@ use std::io;
|
|||||||
///
|
///
|
||||||
/// <https://man.netbsd.org/eventfd.2>
|
/// <https://man.netbsd.org/eventfd.2>
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Event {
|
struct Event {
|
||||||
/// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the
|
/// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the
|
||||||
/// kernel. This counter is initialized with the value specified in the argument initval.
|
/// kernel. This counter is initialized with the value specified in the argument initval.
|
||||||
pub val: Cell<u64>,
|
val: Cell<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileDescriptor for Event {
|
impl FileDescriptor for Event {
|
||||||
@ -70,3 +72,51 @@ impl FileDescriptor for Event {
|
|||||||
Ok(Ok(8))
|
Ok(Ok(8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
|
/// This function creates an `Event` that is used as an event wait/notify mechanism by
|
||||||
|
/// user-space applications, and by the kernel to notify user-space applications of events.
|
||||||
|
/// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
|
||||||
|
/// with the value specified in the `initval` argument.
|
||||||
|
///
|
||||||
|
/// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`,
|
||||||
|
/// `select`, and `close` operations can be performed on the file descriptor. For more
|
||||||
|
/// information on these operations, see the man page linked below.
|
||||||
|
///
|
||||||
|
/// The `flags` are not currently implemented for eventfd.
|
||||||
|
/// The `flags` may be bitwise ORed to change the behavior of `eventfd`:
|
||||||
|
/// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
|
||||||
|
/// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description.
|
||||||
|
/// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
|
||||||
|
///
|
||||||
|
/// <https://linux.die.net/man/2/eventfd>
|
||||||
|
#[expect(clippy::needless_if)]
|
||||||
|
fn eventfd(
|
||||||
|
&mut self,
|
||||||
|
val: &OpTy<'tcx, Provenance>,
|
||||||
|
flags: &OpTy<'tcx, Provenance>,
|
||||||
|
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||||
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
|
let val = this.read_scalar(val)?.to_u32()?;
|
||||||
|
let flags = this.read_scalar(flags)?.to_i32()?;
|
||||||
|
|
||||||
|
let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC");
|
||||||
|
let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK");
|
||||||
|
let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE");
|
||||||
|
|
||||||
|
if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 {
|
||||||
|
throw_unsup_format!("{flags} is unsupported");
|
||||||
|
}
|
||||||
|
// FIXME handle the cloexec and nonblock flags
|
||||||
|
if flags & efd_cloexec == efd_cloexec {}
|
||||||
|
if flags & efd_nonblock == efd_nonblock {}
|
||||||
|
if flags & efd_semaphore == efd_semaphore {
|
||||||
|
throw_unsup_format!("EFD_SEMAPHORE is unsupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
let fd = this.machine.fds.insert_fd(Box::new(Event { val: Cell::new(val.into()) }));
|
||||||
|
Ok(Scalar::from_i32(fd))
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
use crate::*;
|
|
||||||
|
|
||||||
use crate::shims::unix::FileDescriptor;
|
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
/// An `Epoll` file descriptor connects file handles and epoll events
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
pub struct Epoll {
|
|
||||||
/// The file descriptors we are watching, and what we are watching for.
|
|
||||||
pub file_descriptors: FxHashMap<i32, EpollEvent>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Epoll Events associate events with data.
|
|
||||||
/// These fields are currently unused by miri.
|
|
||||||
/// This matches the `epoll_event` struct defined
|
|
||||||
/// by the epoll_ctl man page. For more information
|
|
||||||
/// see the man page:
|
|
||||||
///
|
|
||||||
/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct EpollEvent {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub events: u32,
|
|
||||||
/// `Scalar<Provenance>` is used to represent the
|
|
||||||
/// `epoll_data` type union.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub data: Scalar<Provenance>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileDescriptor for Epoll {
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"epoll"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
|
|
||||||
Ok(Box::new(self.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close<'tcx>(
|
|
||||||
self: Box<Self>,
|
|
||||||
_communicate_allowed: bool,
|
|
||||||
) -> InterpResult<'tcx, io::Result<i32>> {
|
|
||||||
Ok(Ok(0))
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,8 @@ use crate::machine::SIGRTMIN;
|
|||||||
use crate::shims::unix::*;
|
use crate::shims::unix::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use shims::foreign_items::EmulateForeignItemResult;
|
use shims::foreign_items::EmulateForeignItemResult;
|
||||||
use shims::unix::linux::fd::EvalContextExt as _;
|
use shims::unix::linux::epoll::EvalContextExt as _;
|
||||||
|
use shims::unix::linux::eventfd::EvalContextExt as _;
|
||||||
use shims::unix::linux::mem::EvalContextExt as _;
|
use shims::unix::linux::mem::EvalContextExt as _;
|
||||||
use shims::unix::linux::sync::futex;
|
use shims::unix::linux::sync::futex;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod fd;
|
pub mod epoll;
|
||||||
|
pub mod eventfd;
|
||||||
pub mod foreign_items;
|
pub mod foreign_items;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
|
@ -6,7 +6,6 @@ use crate::*;
|
|||||||
/// Pair of connected sockets.
|
/// Pair of connected sockets.
|
||||||
///
|
///
|
||||||
/// We currently don't allow sending any data through this pair, so this can be just a dummy.
|
/// We currently don't allow sending any data through this pair, so this can be just a dummy.
|
||||||
/// FIXME: show proper errors when trying to send/receive
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketPair;
|
struct SocketPair;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user