Skip to content

Commit

Permalink
shims/linux: move epoll and eventfd into their own files, together wi…
Browse files Browse the repository at this point in the history
…th their FD types
  • Loading branch information
RalfJung committed Apr 3, 2024
1 parent a83040d commit 99be2b7
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 106 deletions.
2 changes: 2 additions & 0 deletions src/shims/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub trait FileDescriptor: std::fmt::Debug + Any {
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;

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
}
}
Expand Down
93 changes: 43 additions & 50 deletions src/shims/unix/linux/fd.rs → src/shims/unix/linux/epoll.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,50 @@
use std::cell::Cell;
use std::io;

use rustc_data_structures::fx::FxHashMap;

use crate::shims::unix::*;
use crate::*;
use epoll::{Epoll, EpollEvent};
use event::Event;

pub mod epoll;
pub mod event;
/// An `Epoll` file descriptor connects file handles and epoll events
#[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> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Expand Down Expand Up @@ -156,49 +194,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
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))
}
}
Original file line number Diff line number Diff line change
@@ -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_target::abi::Endian;

use std::cell::Cell;
use std::io;
use crate::shims::unix::*;
use crate::*;

/// A kind of file descriptor created by `eventfd`.
/// The `Event` type isn't currently written to by `eventfd`.
Expand All @@ -15,10 +17,10 @@ use std::io;
///
/// <https://man.netbsd.org/eventfd.2>
#[derive(Debug)]
pub struct Event {
struct Event {
/// 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.
pub val: Cell<u64>,
val: Cell<u64>,
}

impl FileDescriptor for Event {
Expand Down Expand Up @@ -70,3 +72,51 @@ impl FileDescriptor for Event {
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))
}
}
47 changes: 0 additions & 47 deletions src/shims/unix/linux/fd/epoll.rs

This file was deleted.

3 changes: 2 additions & 1 deletion src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::machine::SIGRTMIN;
use crate::shims::unix::*;
use crate::*;
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::sync::futex;

Expand Down
3 changes: 2 additions & 1 deletion src/shims/unix/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod fd;
pub mod epoll;
pub mod eventfd;
pub mod foreign_items;
pub mod mem;
pub mod sync;
1 change: 0 additions & 1 deletion src/shims/unix/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::*;
/// Pair of connected sockets.
///
/// 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)]
struct SocketPair;

Expand Down

0 comments on commit 99be2b7

Please sign in to comment.