Avoid heap allocation on event
This commit is contained in:
Generated
+7
@@ -122,6 +122,7 @@ dependencies = [
|
||||
"rustc-demangle",
|
||||
"sbi-rt",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"spin",
|
||||
"toml",
|
||||
"x86",
|
||||
@@ -289,6 +290,12 @@ version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
|
||||
@@ -18,6 +18,7 @@ redox-path = "0.2.0"
|
||||
redox_syscall = { version = "0.7.3", default-features = false }
|
||||
rmm = { path = "rmm", default-features = false }
|
||||
slab = { version = "0.4", default-features = false }
|
||||
smallvec = { version = "1.15.1", default-features = false }
|
||||
spin = { version = "0.9.8" }
|
||||
# TODO: Remove
|
||||
indexmap = { version = "2.5.0", default-features = false }
|
||||
|
||||
+41
-31
@@ -1,6 +1,7 @@
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use alloc::sync::Arc;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use hashbrown::{hash_map::DefaultHashBuilder, HashMap, HashSet};
|
||||
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
|
||||
use smallvec::SmallVec;
|
||||
use spin::Once;
|
||||
use syscall::data::GlobalSchemes;
|
||||
|
||||
@@ -193,70 +194,79 @@ pub fn unregister_file(scheme: SchemeId, number: usize, token: &mut CleanLockTok
|
||||
//
|
||||
// }
|
||||
|
||||
const MAX_EVENT: usize = 8;
|
||||
|
||||
#[must_use]
|
||||
fn trigger_inner(
|
||||
scheme: SchemeId,
|
||||
number: usize,
|
||||
flags: EventFlags,
|
||||
todo: &mut Vec<EventQueueId>,
|
||||
todo: &mut SmallVec<[EventQueueId; MAX_EVENT]>,
|
||||
offset: &mut usize,
|
||||
token: &mut CleanLockToken,
|
||||
) {
|
||||
let mut matching_keys = Vec::new();
|
||||
) -> bool {
|
||||
let mut matching_keys: SmallVec<[(QueueKey, EventFlags); MAX_EVENT]> = SmallVec::new();
|
||||
let mut full = false;
|
||||
|
||||
{
|
||||
let registry = registry(token);
|
||||
if let Some(queue_list) = registry.get(&RegKey { scheme, number }) {
|
||||
for (queue_key, &queue_flags) in queue_list.iter() {
|
||||
for (queue_key, &queue_flags) in queue_list.iter().skip(*offset) {
|
||||
let common_flags = flags & queue_flags;
|
||||
if !common_flags.is_empty() {
|
||||
if matching_keys.len() == matching_keys.inline_size() {
|
||||
full = true;
|
||||
break;
|
||||
}
|
||||
matching_keys.push((queue_key.clone(), common_flags));
|
||||
}
|
||||
*offset += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut queue_to_send: Vec<(Event, Arc<EventQueue>)> = Vec::new();
|
||||
while let Some((queue_key, common_flags)) = matching_keys.pop() {
|
||||
let Some(queue) = queues(token.token()).get(&queue_key.queue).cloned() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
for (queue_key, common_flags) in matching_keys {
|
||||
let queue_opt = queues(token.token()).get(&queue_key.queue).cloned();
|
||||
let event = Event {
|
||||
id: queue_key.id,
|
||||
flags: common_flags,
|
||||
data: queue_key.data,
|
||||
};
|
||||
|
||||
if let Some(queue) = queue_opt {
|
||||
queue_to_send.push((
|
||||
Event {
|
||||
id: queue_key.id,
|
||||
flags: common_flags,
|
||||
data: queue_key.data,
|
||||
},
|
||||
queue,
|
||||
));
|
||||
todo.push(queue_key.queue);
|
||||
}
|
||||
}
|
||||
|
||||
for (event, queue) in queue_to_send {
|
||||
todo.push(queue_key.queue);
|
||||
queue.queue.send(event, token);
|
||||
if let Some(queue) = Arc::into_inner(queue) {
|
||||
queue.into_drop(token);
|
||||
}
|
||||
}
|
||||
|
||||
full
|
||||
}
|
||||
|
||||
pub fn trigger(scheme: SchemeId, number: usize, flags: EventFlags, token: &mut CleanLockToken) {
|
||||
let mut todo = SmallVec::<[EventQueueId; MAX_EVENT]>::new();
|
||||
let mut done = SmallVec::<[EventQueueId; MAX_EVENT]>::new();
|
||||
|
||||
// First trigger with the original file
|
||||
let mut todo = Vec::new();
|
||||
trigger_inner(scheme, number, flags, &mut todo, token);
|
||||
let mut offset = 0;
|
||||
while trigger_inner(scheme, number, flags, &mut todo, &mut offset, 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(
|
||||
if let Err(insert_idx) = done.binary_search(&queue_id) {
|
||||
done.insert(insert_idx, queue_id);
|
||||
let mut offset = 0;
|
||||
while trigger_inner(
|
||||
GlobalSchemes::Event.scheme_id(),
|
||||
queue_id.into(),
|
||||
EventFlags::EVENT_READ,
|
||||
&mut todo,
|
||||
&mut offset,
|
||||
token,
|
||||
);
|
||||
done.insert(queue_id);
|
||||
) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ use core::{
|
||||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
|
||||
use smallvec::SmallVec;
|
||||
use spin::{Mutex, Once};
|
||||
use syscall::{
|
||||
data::GlobalSchemes,
|
||||
@@ -61,7 +62,7 @@ const INO_PHANDLE: u64 = 0x8003_0000_0000_0000;
|
||||
/// Add to the input queue
|
||||
pub fn irq_trigger(irq: u8, token: &mut CleanLockToken) {
|
||||
COUNTS.lock()[irq as usize] += 1;
|
||||
let fds: Vec<usize> = {
|
||||
let fds: SmallVec<[usize; 8]> = {
|
||||
HANDLES
|
||||
.read(token.token())
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user