shadow_rs/host/syscall/handler/
eventfd.rs

1use std::sync::Arc;
2
3use atomic_refcell::AtomicRefCell;
4use linux_api::errno::Errno;
5use linux_api::fcntl::DescriptorFlags;
6use nix::sys::eventfd::EfdFlags;
7
8use crate::host::descriptor::descriptor_table::DescriptorHandle;
9use crate::host::descriptor::eventfd;
10use crate::host::descriptor::{CompatFile, Descriptor, File, FileStatus, OpenFile};
11use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
12
13impl SyscallHandler {
14    log_syscall!(
15        eventfd,
16        /* rv */ std::ffi::c_int,
17        /* initval */ std::ffi::c_uint,
18    );
19    pub fn eventfd(
20        ctx: &mut SyscallContext,
21        init_val: std::ffi::c_uint,
22    ) -> Result<DescriptorHandle, Errno> {
23        Self::eventfd_helper(ctx, init_val, 0)
24    }
25
26    log_syscall!(
27        eventfd2,
28        /* rv */ std::ffi::c_int,
29        /* initval */ std::ffi::c_uint,
30        /* flags */ nix::sys::eventfd::EfdFlags,
31    );
32    pub fn eventfd2(
33        ctx: &mut SyscallContext,
34        init_val: std::ffi::c_uint,
35        flags: std::ffi::c_int,
36    ) -> Result<DescriptorHandle, Errno> {
37        Self::eventfd_helper(ctx, init_val, flags)
38    }
39
40    fn eventfd_helper(
41        ctx: &mut SyscallContext,
42        init_val: std::ffi::c_uint,
43        flags: std::ffi::c_int,
44    ) -> Result<DescriptorHandle, Errno> {
45        log::trace!("eventfd() called with initval {init_val} and flags {flags}");
46
47        // get the flags
48        let flags = match EfdFlags::from_bits(flags) {
49            Some(x) => x,
50            None => {
51                log::warn!("Invalid eventfd flags: {}", flags);
52                return Err(Errno::EINVAL);
53            }
54        };
55
56        let mut file_flags = FileStatus::empty();
57        let mut descriptor_flags = DescriptorFlags::empty();
58        let mut semaphore_mode = false;
59
60        if flags.contains(EfdFlags::EFD_NONBLOCK) {
61            file_flags.insert(FileStatus::NONBLOCK);
62        }
63
64        if flags.contains(EfdFlags::EFD_CLOEXEC) {
65            descriptor_flags.insert(DescriptorFlags::FD_CLOEXEC);
66        }
67
68        if flags.contains(EfdFlags::EFD_SEMAPHORE) {
69            semaphore_mode = true;
70        }
71
72        let file = eventfd::EventFd::new(init_val as u64, semaphore_mode, file_flags);
73        let file = Arc::new(AtomicRefCell::new(file));
74
75        let mut desc = Descriptor::new(CompatFile::New(OpenFile::new(File::EventFd(file))));
76        desc.set_flags(descriptor_flags);
77
78        let fd = ctx
79            .objs
80            .thread
81            .descriptor_table_borrow_mut(ctx.objs.host)
82            .register_descriptor(desc)
83            .or(Err(Errno::ENFILE))?;
84
85        log::trace!("eventfd() returning fd {}", fd);
86
87        Ok(fd)
88    }
89}