From 65e8abb449e8caec8d7358f29e6340814e07a050 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 14 Feb 2020 18:43:48 +0100 Subject: [PATCH] Allow multiple processes to share IRQs. I haven't been able to receive xhc interrupt anyway. --- src/scheme/irq.rs | 57 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 60bcdd2c..a238698c 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -1,6 +1,8 @@ use core::{mem, str}; -use core::sync::atomic::Ordering; -use spin::Mutex; +use core::sync::atomic::{AtomicUsize, Ordering}; +use spin::{Mutex, RwLock}; + +use alloc::collections::BTreeMap; use crate::event; use crate::interrupt::irq::acknowledge; @@ -12,22 +14,42 @@ use crate::syscall::scheme::Scheme; pub static IRQ_SCHEME_ID: AtomicSchemeId = AtomicSchemeId::default(); /// IRQ queues -static ACKS: Mutex<[usize; 16]> = Mutex::new([0; 16]); static COUNTS: Mutex<[usize; 16]> = Mutex::new([0; 16]); +static HANDLES: RwLock<Option<BTreeMap<usize, Handle>>> = RwLock::new(None); /// Add to the input queue #[no_mangle] pub extern fn irq_trigger(irq: u8) { COUNTS.lock()[irq as usize] += 1; - event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), irq as usize, EVENT_READ); + + let guard = HANDLES.read(); + if let Some(handles) = guard.as_ref() { + for (fd, _) in handles.iter().filter(|(_, handle)| handle.irq == irq) { + event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), *fd, EVENT_READ); + } + } else { + println!("Calling IRQ without triggering"); + } } -pub struct IrqScheme; +struct Handle { + ack: AtomicUsize, + irq: u8, +} + +pub struct IrqScheme { + next_fd: AtomicUsize, +} impl IrqScheme { pub fn new(scheme_id: SchemeId) -> IrqScheme { IRQ_SCHEME_ID.store(scheme_id, Ordering::SeqCst); - IrqScheme + + *HANDLES.write() = Some(BTreeMap::new()); + + IrqScheme { + next_fd: AtomicUsize::new(0), + } } } @@ -39,7 +61,9 @@ impl Scheme for IrqScheme { let id = path_str.parse::<usize>().or(Err(Error::new(ENOENT)))?; if id < COUNTS.lock().len() { - Ok(id) + let fd = self.next_fd.fetch_add(1, Ordering::Relaxed); + HANDLES.write().as_mut().unwrap().insert(fd, Handle { ack: AtomicUsize::new(0), irq: id as u8 }); + Ok(fd) } else { Err(Error::new(ENOENT)) } @@ -51,9 +75,11 @@ impl Scheme for IrqScheme { fn read(&self, file: usize, buffer: &mut [u8]) -> Result<usize> { // Ensures that the length of the buffer is larger than the size of a usize if buffer.len() >= mem::size_of::<usize>() { - let ack = ACKS.lock()[file]; - let current = COUNTS.lock()[file]; - if ack != current { + let handles_guard = HANDLES.read(); + let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + + let current = COUNTS.lock()[handle.irq as usize]; + if handle.ack.load(Ordering::SeqCst) != current { // Safe if the length of the buffer is larger than the size of a usize assert!(buffer.len() >= mem::size_of::<usize>()); unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } @@ -69,11 +95,16 @@ impl Scheme for IrqScheme { fn write(&self, file: usize, buffer: &[u8]) -> Result<usize> { if buffer.len() >= mem::size_of::<usize>() { assert!(buffer.len() >= mem::size_of::<usize>()); + + let handles_guard = HANDLES.read(); + let handle = &handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; + let ack = unsafe { *(buffer.as_ptr() as *const usize) }; - let current = COUNTS.lock()[file]; + let current = COUNTS.lock()[handle.irq as usize]; + if ack == current { - ACKS.lock()[file] = ack; - unsafe { acknowledge(file); } + handle.ack.store(ack, Ordering::SeqCst); + unsafe { acknowledge(handle.irq as usize); } Ok(mem::size_of::<usize>()) } else { Ok(0) -- GitLab