Recursively trigger event queues
This commit is contained in:
+41
-8
@@ -1,11 +1,11 @@
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use hashbrown::HashMap;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use spin::Once;
|
||||
|
||||
use crate::{
|
||||
context,
|
||||
scheme::{self, SchemeId},
|
||||
scheme::{self, GlobalSchemes, SchemeId},
|
||||
sync::{
|
||||
CleanLockToken, LockToken, RwLock, RwLockReadGuard, RwLockWriteGuard, WaitQueue, L0, L1,
|
||||
},
|
||||
@@ -32,6 +32,10 @@ impl EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_currently_empty(&self) -> bool {
|
||||
self.queue.is_currently_empty()
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: UserSliceWo, block: bool, token: &mut CleanLockToken) -> Result<usize> {
|
||||
self.queue
|
||||
.receive_into_user(buf, block, "EventQueue::read", token)
|
||||
@@ -179,10 +183,13 @@ pub fn unregister_file(scheme: SchemeId, number: usize) {
|
||||
//
|
||||
// }
|
||||
|
||||
pub fn trigger(scheme: SchemeId, number: usize, flags: EventFlags) {
|
||||
//TODO: propogate this lock token
|
||||
let mut token = unsafe { CleanLockToken::new() };
|
||||
|
||||
fn trigger_inner(
|
||||
scheme: SchemeId,
|
||||
number: usize,
|
||||
flags: EventFlags,
|
||||
todo: &mut Vec<EventQueueId>,
|
||||
token: &mut CleanLockToken,
|
||||
) {
|
||||
let registry = registry();
|
||||
if let Some(queue_list) = registry.get(&RegKey { scheme, number }) {
|
||||
for (queue_key, &queue_flags) in queue_list.iter() {
|
||||
@@ -199,10 +206,36 @@ pub fn trigger(scheme: SchemeId, number: usize, flags: EventFlags) {
|
||||
flags: common_flags,
|
||||
data: queue_key.data,
|
||||
},
|
||||
&mut token,
|
||||
token,
|
||||
);
|
||||
todo.push(queue_key.queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trigger(scheme: SchemeId, number: usize, flags: EventFlags) {
|
||||
//TODO: propogate this lock token
|
||||
let mut token = unsafe { CleanLockToken::new() };
|
||||
|
||||
// First trigger with the original file
|
||||
let mut todo = Vec::new();
|
||||
trigger_inner(scheme, number, flags, &mut todo, &mut token);
|
||||
|
||||
// Handle triggers on queues
|
||||
//TODO: can this be done with limited allocations?
|
||||
let mut done = HashSet::new();
|
||||
while let Some(queue_id) = todo.pop() {
|
||||
if !done.contains(&queue_id) {
|
||||
trigger_inner(
|
||||
GlobalSchemes::Event.scheme_id(),
|
||||
queue_id.into(),
|
||||
EventFlags::EVENT_READ,
|
||||
&mut todo,
|
||||
&mut token,
|
||||
);
|
||||
done.insert(queue_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-1
@@ -1,6 +1,6 @@
|
||||
use alloc::sync::Arc;
|
||||
use core::mem;
|
||||
use syscall::O_NONBLOCK;
|
||||
use syscall::{EventFlags, O_NONBLOCK};
|
||||
|
||||
use crate::{
|
||||
context::file::InternalFlags,
|
||||
@@ -38,6 +38,7 @@ impl KernelScheme for EventScheme {
|
||||
.ok_or(Error::new(EBADF))
|
||||
.and(Ok(()))
|
||||
}
|
||||
|
||||
fn kread(
|
||||
&self,
|
||||
id: usize,
|
||||
@@ -88,4 +89,30 @@ impl KernelScheme for EventScheme {
|
||||
fn kfpath(&self, _id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> {
|
||||
buf.copy_common_bytes_from_slice(b"event:")
|
||||
}
|
||||
|
||||
fn fevent(
|
||||
&self,
|
||||
id: usize,
|
||||
flags: EventFlags,
|
||||
token: &mut CleanLockToken,
|
||||
) -> Result<EventFlags> {
|
||||
let id = EventQueueId::from(id);
|
||||
|
||||
let queue = {
|
||||
let handles = queues(token.token());
|
||||
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.clone()
|
||||
};
|
||||
|
||||
let mut ready = EventFlags::empty();
|
||||
if flags.contains(EventFlags::EVENT_WRITE) {
|
||||
// It is always possible to write events
|
||||
ready |= EventFlags::EVENT_WRITE;
|
||||
}
|
||||
if flags.contains(EventFlags::EVENT_READ) && !queue.is_currently_empty() {
|
||||
// It is possible to read if queue is not empty
|
||||
ready |= EventFlags::EVENT_READ;
|
||||
}
|
||||
Ok(ready)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user