feat(kernel): add WaitForInterrupt, AcknowledgeInterrupt, and WaitAny syscalls

This commit is contained in:
2026-10-18 00:26:11 +02:00
parent e7835c0435
commit 8912a944b8
4 changed files with 260 additions and 5 deletions

View File

@@ -1,10 +1,10 @@
use super::*;
use crate::{SyscallOutcome, SyscallResult};
use domain::message::Message;
use domain::syscall::Syscall;
use domain::syscall::{Syscall, WaitSet, WakeReason};
use domain::thread::BlockReason;
use types::bounded::CapSlot;
use types::id::ThreadId;
use types::id::{IrqId, ThreadId};
use types::permission::{Permission, PermissionSet};
fn setup_ipc_kernel() -> (
@@ -138,3 +138,96 @@ fn send_checks_endpoint_capability() {
SyscallOutcome::Complete(SyscallResult::Error(_))
));
}
// --- WaitForInterrupt / AcknowledgeInterrupt ---
#[test]
fn wait_for_interrupt_blocks_caller() {
let (mut k, pid_a, _, _, _, _) = setup_ipc_kernel();
let irq = IrqId::from_raw(7);
let irq_slot = k.grant_cap_for_test(
pid_a,
domain::resource::Resource::Interrupt(irq),
PermissionSet::empty()
.with(Permission::Read)
.with(Permission::Write),
);
let outcome = k.handle_syscall(Syscall::WaitForInterrupt { irq: irq_slot });
assert!(matches!(
outcome,
SyscallOutcome::BlockCaller(BlockReason::WaitingForInterrupt(_))
));
}
#[test]
fn ack_interrupt_returns_ok() {
let (mut k, pid_a, _, _, _, _) = setup_ipc_kernel();
let irq = IrqId::from_raw(7);
let irq_slot = k.grant_cap_for_test(
pid_a,
domain::resource::Resource::Interrupt(irq),
PermissionSet::empty().with(Permission::Write),
);
let outcome = k.handle_syscall(Syscall::AcknowledgeInterrupt { irq: irq_slot });
assert!(matches!(
outcome,
SyscallOutcome::Complete(SyscallResult::Ok)
));
}
// --- WaitAny ---
#[test]
fn wait_any_with_ready_source_returns_immediately() {
let (mut k, pid_a, _, cap_a, cap_b, tid_b) = setup_ipc_kernel();
let tid_a = ThreadId::from_raw(0);
// Thread B sends a message (blocks since no receiver)
k.switch_to_thread_for_test(tid_b);
k.handle_syscall(Syscall::Send {
endpoint: cap_b,
message: Message::from_words([77, 0, 0, 0]),
});
// Thread A does WaitAny on the endpoint
k.switch_to_thread_for_test(tid_a);
let wait_set = WaitSet::new(
[Some(cap_a), None, None, None],
[None, None, None, None],
);
let outcome = k.handle_syscall(Syscall::WaitAny { sources: wait_set });
assert!(matches!(
outcome,
SyscallOutcome::Complete(SyscallResult::WakeReason(WakeReason::MessageReady(_)))
));
}
#[test]
fn wait_any_with_no_ready_source_blocks() {
let (mut k, pid_a, _, cap_a, _, _) = setup_ipc_kernel();
let wait_set = WaitSet::new(
[Some(cap_a), None, None, None],
[None, None, None, None],
);
let outcome = k.handle_syscall(Syscall::WaitAny { sources: wait_set });
assert!(matches!(
outcome,
SyscallOutcome::BlockCaller(BlockReason::WaitingAny)
));
}
#[test]
fn wait_any_empty_sources_returns_error() {
let (mut k, _, _, _, _, _) = setup_ipc_kernel();
let wait_set = WaitSet::new(
[None, None, None, None],
[None, None, None, None],
);
let outcome = k.handle_syscall(Syscall::WaitAny { sources: wait_set });
assert!(matches!(
outcome,
SyscallOutcome::Complete(SyscallResult::Error(_))
));
}