• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::fs::File;
15 use std::io;
16 use std::io::{Read, Write};
17 use std::os::unix::io::FromRawFd;
18 
19 use crate::{Interest, Selector, Token};
20 
21 /// In Linux, `eventfd` is used to implement asynchronous wake-up. It is a
22 /// 64-bit counter. A fixed 8-byte (64-bit) unsigned integer is written to
23 /// ensure wake-up reliability.
24 #[derive(Debug)]
25 pub(crate) struct WakerInner {
26     fd: File,
27 }
28 impl WakerInner {
new(selector: &Selector, token: Token) -> io::Result<WakerInner>29     pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<WakerInner> {
30         let fd = unsafe { libc::eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK) };
31         let file = unsafe { File::from_raw_fd(fd) };
32         if fd == -1 {
33             let err = io::Error::last_os_error();
34             Err(err)
35         } else {
36             selector
37                 .register(fd, token, Interest::READABLE)
38                 .map(|()| WakerInner { fd: file })
39         }
40     }
41 
wake(&self) -> io::Result<()>42     pub(crate) fn wake(&self) -> io::Result<()> {
43         let buf: [u8; 8] = 1u64.to_ne_bytes();
44         match (&self.fd).write(&buf) {
45             Ok(_) => Ok(()),
46             Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
47                 let mut buf: [u8; 8] = 0u64.to_ne_bytes();
48                 match (&self.fd).read(&mut buf) {
49                     Err(err) if err.kind() != io::ErrorKind::WouldBlock => Err(err),
50                     _ => self.wake(),
51                 }
52             }
53             Err(err) => Err(err),
54         }
55     }
56 }
57