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 std::ffi::c_int,
17 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 std::ffi::c_int,
29 std::ffi::c_uint,
30 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 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}