fix: sched round-robin, cap slot OOB panic, clippy, make ci

- RunList -> intrusive FIFO, no starvation, no silent drop
- cap table sized to CapSlot range (kani caught OOB panic)
- snake food color test uses const
- kani cfg lint, RUST_MIN_STACK for big kernel struct in tests
This commit is contained in:
2026-10-26 19:08:30 +01:00
parent 1c04ddf909
commit e931485ca7
32 changed files with 384 additions and 251 deletions

View File

@@ -42,11 +42,11 @@ impl<P: Platform> Kernel<P> {
return SyscallOutcome::Complete(SyscallResult::Error(e));
}
if let domain::resource::Resource::Memory(region_id) = &resource {
if let Some(region) = self.regions.get(*region_id) {
self.platform
.map_shared(target_pid, region.base(), region.size(), restricted);
}
if let domain::resource::Resource::Memory(region_id) = &resource
&& let Some(region) = self.regions.get(*region_id)
{
self.platform
.map_shared(target_pid, region.base(), region.size(), restricted);
}
SyscallOutcome::Complete(SyscallResult::Ok)

View File

@@ -15,34 +15,31 @@ impl<P: Platform> Kernel<P> {
};
// Try to deliver fault to a fault handler endpoint (if configured)
if let Ok(process) = self.processes.get(pid) {
if let Some(handler_slot) = process.fault_handler() {
if let Ok(cap) = process.capabilities().get(handler_slot) {
if let domain::resource::Resource::Endpoint(ep_id) = cap.resource() {
let msg = domain::message::Message::from_words([
pid.raw() as usize,
fault.code(),
fault.address(),
fault_pc,
]);
if let Ok(process) = self.processes.get(pid)
&& let Some(handler_slot) = process.fault_handler()
&& let Ok(cap) = process.capabilities().get(handler_slot)
&& let domain::resource::Resource::Endpoint(ep_id) = cap.resource()
{
let msg = domain::message::Message::from_words([
pid.raw() as usize,
fault.code(),
fault.address(),
fault_pc,
]);
if let Some(ep) = self.endpoints.get_mut(*ep_id) {
if ep.has_waiting_receiver() {
if let Some(receiver_tid) = ep.dequeue_receiver() {
self.pending_results[receiver_tid.raw() as usize] =
Some(crate::SyscallResult::Message(msg));
if let Some(ep) = self.endpoints.get_mut(*ep_id)
&& ep.has_waiting_receiver()
&& let Some(receiver_tid) = ep.dequeue_receiver()
{
self.pending_results[receiver_tid.raw() as usize] =
Some(crate::SyscallResult::Message(msg));
if let Ok(receiver) = self.threads.get_mut(receiver_tid) {
let priority = receiver.priority();
let _ = receiver.unblock();
let core = self.platform.core_id();
use domain::scheduler::Scheduler;
self.scheduler.add(receiver_tid, priority, core);
}
}
}
}
}
if let Ok(receiver) = self.threads.get_mut(receiver_tid) {
let priority = receiver.priority();
let _ = receiver.unblock();
let core = self.platform.core_id();
use domain::scheduler::Scheduler;
self.scheduler.add(receiver_tid, priority, core);
}
}
}

View File

@@ -180,7 +180,7 @@ impl<P: Platform> Kernel<P> {
message.is_some(),
"sender in wait queue had no pending message"
);
let message = message.unwrap_or_else(|| domain::message::Message::empty());
let message = message.unwrap_or_else(domain::message::Message::empty);
self.pending_results[sender_tid.raw() as usize] = Some(SyscallResult::Ok);
@@ -289,54 +289,46 @@ impl<P: Platform> Kernel<P> {
));
}
for ep_slot in sources.endpoints() {
if let Some(slot) = ep_slot {
let ep_id =
match self.check_cap(caller_pid, *slot, types::permission::Permission::Read) {
Ok(cap) => match cap.resource() {
domain::resource::Resource::Endpoint(id) => *id,
_ => continue,
},
Err(_) => continue,
};
for slot in sources.endpoints().iter().flatten() {
let ep_id = match self.check_cap(caller_pid, *slot, types::permission::Permission::Read)
{
Ok(cap) => match cap.resource() {
domain::resource::Resource::Endpoint(id) => *id,
_ => continue,
},
Err(_) => continue,
};
if let Some(ep) = self.endpoints.get_mut(ep_id) {
if ep.has_waiting_sender() {
return SyscallOutcome::Complete(SyscallResult::WakeReason(
domain::syscall::WakeReason::MessageReady(*slot),
));
}
}
if let Some(ep) = self.endpoints.get_mut(ep_id)
&& ep.has_waiting_sender()
{
return SyscallOutcome::Complete(SyscallResult::WakeReason(
domain::syscall::WakeReason::MessageReady(*slot),
));
}
}
for irq_slot in sources.interrupts() {
if let Some(slot) = irq_slot {
if let Ok(cap) =
if let Some(slot) = irq_slot
&& let Ok(cap) =
self.check_cap(caller_pid, *slot, types::permission::Permission::Read)
{
if let domain::resource::Resource::Interrupt(irq_id) = cap.resource() {
if self.irqs.owner(*irq_id).is_some() {
return SyscallOutcome::Complete(SyscallResult::WakeReason(
domain::syscall::WakeReason::InterruptFired(*slot),
));
}
}
}
&& let domain::resource::Resource::Interrupt(irq_id) = cap.resource()
&& self.irqs.owner(*irq_id).is_some()
{
return SyscallOutcome::Complete(SyscallResult::WakeReason(
domain::syscall::WakeReason::InterruptFired(*slot),
));
}
}
for ep_slot in sources.endpoints() {
if let Some(slot) = ep_slot {
if let Ok(cap) =
if let Some(slot) = ep_slot
&& let Ok(cap) =
self.check_cap(caller_pid, *slot, types::permission::Permission::Read)
{
if let domain::resource::Resource::Endpoint(id) = cap.resource() {
if let Some(ep) = self.endpoints.get_mut(*id) {
let _ = ep.enqueue_receiver(caller_tid);
}
}
}
&& let domain::resource::Resource::Endpoint(id) = cap.resource()
&& let Some(ep) = self.endpoints.get_mut(*id)
{
let _ = ep.enqueue_receiver(caller_tid);
}
}

View File

@@ -1,4 +1,3 @@
use domain::process::MAX_THREADS_PER_PROCESS;
use platform::Platform;
use super::{SyscallOutcome, SyscallResult};