sys_util/eventfd.rs
1// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::fs::File;
6use std::mem;
7use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
8
9use libc::{c_void, dup, eventfd, read, write};
10
11use {errno_result, Result};
12
13/// A safe wrapper around a Linux eventfd (man 2 eventfd).
14///
15/// An eventfd is useful because it is sendable across processes and can be used for signaling in
16/// and out of the KVM API. They can also be polled like any other file descriptor.
17#[derive(Debug)]
18pub struct EventFd {
19 eventfd: File,
20}
21
22impl EventFd {
23 /// Creates a new blocking EventFd with an initial value of 0.
24 pub fn new() -> Result<EventFd> {
25 // This is safe because eventfd merely allocated an eventfd for our process and we handle
26 // the error case.
27 let ret = unsafe { eventfd(0, 0) };
28 if ret < 0 {
29 return errno_result();
30 }
31 // This is safe because we checked ret for success and know the kernel gave us an fd that we
32 // own.
33 Ok(EventFd {
34 eventfd: unsafe { File::from_raw_fd(ret) },
35 })
36 }
37
38 /// Adds `v` to the eventfd's count, blocking until this won't overflow the count.
39 pub fn write(&self, v: u64) -> Result<()> {
40 // This is safe because we made this fd and the pointer we pass can not overflow because we
41 // give the syscall's size parameter properly.
42 let ret = unsafe {
43 write(
44 self.as_raw_fd(),
45 &v as *const u64 as *const c_void,
46 mem::size_of::<u64>(),
47 )
48 };
49 if ret <= 0 {
50 return errno_result();
51 }
52 Ok(())
53 }
54
55 /// Blocks until the the eventfd's count is non-zero, then resets the count to zero.
56 pub fn read(&self) -> Result<u64> {
57 let mut buf: u64 = 0;
58 let ret = unsafe {
59 // This is safe because we made this fd and the pointer we pass can not overflow because
60 // we give the syscall's size parameter properly.
61 read(
62 self.as_raw_fd(),
63 &mut buf as *mut u64 as *mut c_void,
64 mem::size_of::<u64>(),
65 )
66 };
67 if ret <= 0 {
68 return errno_result();
69 }
70 Ok(buf)
71 }
72
73 /// Clones this EventFd, internally creating a new file descriptor. The new EventFd will share
74 /// the same underlying count within the kernel.
75 pub fn try_clone(&self) -> Result<EventFd> {
76 // This is safe because we made this fd and properly check that it returns without error.
77 let ret = unsafe { dup(self.as_raw_fd()) };
78 if ret < 0 {
79 return errno_result();
80 }
81 // This is safe because we checked ret for success and know the kernel gave us an fd that we
82 // own.
83 Ok(EventFd {
84 eventfd: unsafe { File::from_raw_fd(ret) },
85 })
86 }
87}
88
89impl AsRawFd for EventFd {
90 fn as_raw_fd(&self) -> RawFd {
91 self.eventfd.as_raw_fd()
92 }
93}
94
95impl FromRawFd for EventFd {
96 unsafe fn from_raw_fd(fd: RawFd) -> Self {
97 EventFd {
98 eventfd: File::from_raw_fd(fd),
99 }
100 }
101}
102
103impl IntoRawFd for EventFd {
104 fn into_raw_fd(self) -> RawFd {
105 self.eventfd.into_raw_fd()
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn new() {
115 EventFd::new().unwrap();
116 }
117
118 #[test]
119 fn read_write() {
120 let evt = EventFd::new().unwrap();
121 evt.write(55).unwrap();
122 assert_eq!(evt.read(), Ok(55));
123 }
124
125 #[test]
126 fn clone() {
127 let evt = EventFd::new().unwrap();
128 let evt_clone = evt.try_clone().unwrap();
129 evt.write(923).unwrap();
130 assert_eq!(evt_clone.read(), Ok(923));
131 }
132}