1 // Copyright 2019 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 std::sync::Arc; 6 7 use anyhow::Context; 8 use base::debug; 9 use base::error; 10 use base::Event; 11 use base::EventType; 12 use sync::Mutex; 13 14 use super::interrupter::Interrupter; 15 use crate::utils::EventHandler; 16 use crate::utils::EventLoop; 17 18 /// Interrupt Resample handler handles resample event. It will reassert interrupt if needed. 19 pub struct IntrResampleHandler { 20 interrupter: Arc<Mutex<Interrupter>>, 21 resample_evt: Event, 22 } 23 24 impl IntrResampleHandler { 25 /// Start resample handler. start( event_loop: &EventLoop, interrupter: Arc<Mutex<Interrupter>>, resample_evt: Event, ) -> Option<Arc<IntrResampleHandler>>26 pub fn start( 27 event_loop: &EventLoop, 28 interrupter: Arc<Mutex<Interrupter>>, 29 resample_evt: Event, 30 ) -> Option<Arc<IntrResampleHandler>> { 31 let handler = Arc::new(IntrResampleHandler { 32 interrupter, 33 resample_evt, 34 }); 35 let tmp_handler: Arc<dyn EventHandler> = handler.clone(); 36 if let Err(e) = event_loop.add_event( 37 &handler.resample_evt, 38 EventType::Read, 39 Arc::downgrade(&tmp_handler), 40 ) { 41 error!("cannot add intr resample handler to event loop: {}", e); 42 return None; 43 } 44 Some(handler) 45 } 46 } 47 48 impl EventHandler for IntrResampleHandler { on_event(&self) -> anyhow::Result<()>49 fn on_event(&self) -> anyhow::Result<()> { 50 self.resample_evt 51 .wait() 52 .context("cannot read resample evt")?; 53 let mut interrupter = self.interrupter.lock(); 54 if !interrupter.event_ring_is_empty() { 55 debug!("irq resample re-assert irq event"); 56 // There could be a race condition. When we get resample_evt and other 57 // component is sending interrupt at the same time. 58 // This might result in one more interrupt than we want. It's handled by 59 // kernel correctly. 60 interrupter.interrupt().context("cannot send interrupt")?; 61 } 62 Ok(()) 63 } 64 } 65