Avoid heap allocation on event

This commit is contained in:
Wildan M
2026-03-07 19:04:32 +07:00
committed by Jeremy Soller
parent 4ccc521156
commit a5adc0cc69
4 changed files with 51 additions and 32 deletions
Generated
+7
View File
@@ -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"
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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()