1 // Copyright 2024 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use nix::sys::epoll::Epoll; 6 use nix::sys::epoll::EpollCreateFlags; 7 use nix::sys::epoll::EpollEvent; 8 use nix::sys::epoll::EpollFlags; 9 use nix::sys::epoll::EpollTimeout; 10 11 use crate::rutabaga_os::OwnedDescriptor; 12 use crate::rutabaga_os::WaitEvent; 13 use crate::rutabaga_os::WaitTimeout; 14 use crate::rutabaga_os::WAIT_CONTEXT_MAX; 15 use crate::rutabaga_utils::RutabagaResult; 16 17 pub struct WaitContext { 18 epoll_ctx: Epoll, 19 } 20 21 impl WaitContext { new() -> RutabagaResult<WaitContext>22 pub fn new() -> RutabagaResult<WaitContext> { 23 let epoll = Epoll::new(EpollCreateFlags::empty())?; 24 Ok(WaitContext { epoll_ctx: epoll }) 25 } 26 add(&mut self, connection_id: u64, descriptor: &OwnedDescriptor) -> RutabagaResult<()>27 pub fn add(&mut self, connection_id: u64, descriptor: &OwnedDescriptor) -> RutabagaResult<()> { 28 self.epoll_ctx.add( 29 descriptor, 30 EpollEvent::new(EpollFlags::EPOLLIN, connection_id), 31 )?; 32 Ok(()) 33 } 34 wait(&mut self, timeout: WaitTimeout) -> RutabagaResult<Vec<WaitEvent>>35 pub fn wait(&mut self, timeout: WaitTimeout) -> RutabagaResult<Vec<WaitEvent>> { 36 let mut events = [EpollEvent::empty(); WAIT_CONTEXT_MAX]; 37 38 let epoll_timeout = match timeout { 39 WaitTimeout::Finite(duration) => { 40 // We shouldn't need timeouts greater than 60s. 41 let timeout: u16 = duration.as_millis().try_into().unwrap_or(u16::MAX); 42 EpollTimeout::from(timeout) 43 } 44 WaitTimeout::NoTimeout => EpollTimeout::NONE, 45 }; 46 47 let count = loop { 48 match self.epoll_ctx.wait(&mut events, epoll_timeout) { 49 Err(nix::errno::Errno::EINTR) => (), 50 result => break result?, 51 } 52 }; 53 54 let events = events[0..count] 55 .iter() 56 .map(|e| WaitEvent { 57 connection_id: e.data(), 58 readable: e.events() & EpollFlags::EPOLLIN == EpollFlags::EPOLLIN, 59 hung_up: e.events() & EpollFlags::EPOLLHUP == EpollFlags::EPOLLHUP, 60 }) 61 .collect(); 62 63 Ok(events) 64 } 65 delete(&mut self, descriptor: &OwnedDescriptor) -> RutabagaResult<()>66 pub fn delete(&mut self, descriptor: &OwnedDescriptor) -> RutabagaResult<()> { 67 self.epoll_ctx.delete(descriptor)?; 68 Ok(()) 69 } 70 } 71