nix/sys/eventfd.rs
1use crate::errno::Errno;
2use crate::{unistd, Result};
3use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
4
5libc_bitflags! {
6 /// Eventfd flags.
7 pub struct EfdFlags: libc::c_int {
8 /// Set the close-on-exec (`FD_CLOEXEC`) flag on the new event file descriptor.
9 EFD_CLOEXEC; // Since Linux 2.6.27/FreeBSD 13.0
10 /// Set the `O_NONBLOCK` file status flag on the new event file description.
11 EFD_NONBLOCK; // Since Linux 2.6.27/FreeBSD 13.0
12 /// Provide semaphore-like semantics for reads from the new event file
13 /// descriptor.
14 EFD_SEMAPHORE; // Since Linux 2.6.30/FreeBSD 13.0
15 }
16}
17
18#[deprecated(
19 since = "0.28.0",
20 note = "Use EventFd::from_value_and_flags() instead"
21)]
22#[allow(missing_docs)]
23pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
24 let res = unsafe { libc::eventfd(initval, flags.bits()) };
25
26 Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) })
27}
28
29/// An eventfd file descriptor.
30#[derive(Debug)]
31#[repr(transparent)]
32pub struct EventFd(OwnedFd);
33
34impl EventFd {
35 /// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`.
36 pub fn new() -> Result<Self> {
37 Self::from_value_and_flags(0, EfdFlags::empty())
38 }
39
40 /// Constructs [`EventFd`] with the given `init_val` and `flags`.
41 ///
42 /// Wrapper around [`libc::eventfd`].
43 pub fn from_value_and_flags(
44 init_val: u32,
45 flags: EfdFlags,
46 ) -> Result<Self> {
47 let res = unsafe { libc::eventfd(init_val, flags.bits()) };
48 Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) }))
49 }
50
51 /// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`.
52 pub fn from_flags(flags: EfdFlags) -> Result<Self> {
53 Self::from_value_and_flags(0, flags)
54 }
55
56 /// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`.
57 pub fn from_value(init_val: u32) -> Result<Self> {
58 Self::from_value_and_flags(init_val, EfdFlags::empty())
59 }
60
61 /// Constructs an `EventFd` wrapping an existing `OwnedFd`.
62 ///
63 /// # Safety
64 ///
65 /// `OwnedFd` is a valid eventfd.
66 pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
67 Self(fd)
68 }
69
70 /// Enqueues `value` triggers, i.e., adds the integer value supplied in `value`
71 /// to the counter.
72 ///
73 /// The next `value` calls to `poll`, `select` or `epoll` will return immediately.
74 ///
75 /// [`EventFd::write`] with `value`.
76 pub fn write(&self, value: u64) -> Result<usize> {
77 unistd::write(&self.0, &value.to_ne_bytes())
78 }
79
80 /// Reads the value from the file descriptor.
81 ///
82 /// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was not specified and
83 /// the eventfd counter has a nonzero value, then this function returns
84 /// an `u64` containing that value, and the counter's value is reset to
85 /// zero.
86 ///
87 /// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was specified and the
88 /// eventfd counter has a nonzero value, then this function returns an
89 /// `u64` containing the value 1, and the counter's value is decremented
90 /// by 1.
91 ///
92 /// * If the eventfd counter is zero at the time of this call, then the
93 /// call either blocks until the counter becomes nonzero (at which time,
94 /// this function proceeds as described above) or fails with the error
95 /// `EAGAIN` if the file descriptor has been made nonblocking with
96 /// [`EFD_NONBLOCK`](EfdFlags::EFD_NONBLOCK).
97 pub fn read(&self) -> Result<u64> {
98 let mut arr = [0; std::mem::size_of::<u64>()];
99 unistd::read(&self.0, &mut arr)?;
100 Ok(u64::from_ne_bytes(arr))
101 }
102}
103impl AsFd for EventFd {
104 fn as_fd(&self) -> BorrowedFd {
105 self.0.as_fd()
106 }
107}
108impl AsRawFd for EventFd {
109 fn as_raw_fd(&self) -> RawFd {
110 self.0.as_raw_fd()
111 }
112}
113
114impl From<EventFd> for OwnedFd {
115 fn from(value: EventFd) -> Self {
116 value.0
117 }
118}