feat(userspace): Call/ReplyRecv IPC, malformed-request replies, servers exit on dead endpoint; drop send/receive compat, select!, async_syscall

This commit is contained in:
2026-10-27 12:06:10 +01:00
parent 2a8a5b0c27
commit e8a2963b24
18 changed files with 96 additions and 101 deletions

View File

@@ -2,9 +2,10 @@ use crate::syscall;
use types::bounded::CapSlot;
use types::display::{Color, Dimension, ScreenCoord};
/// A failed call reads as an error reply (tag `usize::MAX`).
fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) {
syscall::send(ep, w0, w1, w2, w3);
syscall::receive(ep)
let r = syscall::request(ep, [w0, w1, w2, w3]).unwrap_or([usize::MAX, 0, 0, 0]);
(r[0], r[1], r[2], r[3])
}
pub fn draw_rect(

View File

@@ -23,9 +23,10 @@ fn pack_path(path: &[u8]) -> (usize, usize) {
(usize::from_le_bytes(w0), usize::from_le_bytes(w1))
}
/// A failed call reads as an error reply (tag `usize::MAX`).
fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) {
syscall::send(ep, w0, w1, w2, w3);
syscall::receive(ep)
let r = syscall::request(ep, [w0, w1, w2, w3]).unwrap_or([usize::MAX, 0, 0, 0]);
(r[0], r[1], r[2], r[3])
}
pub fn open(ep: CapSlot, path: &[u8]) -> Option<FileHandle> {

View File

@@ -38,8 +38,7 @@ fn decode_key(kind: usize, extra: usize) -> Option<Key> {
}
pub fn poll_event(ep: CapSlot) -> Option<InputEvent> {
syscall::send(ep, 0, 0, 0, 0);
let (tag, kind, extra, _) = syscall::receive(ep);
let [tag, kind, extra, _] = syscall::request(ep, [0; 4]).ok()?;
match tag {
0 => None,
1 => decode_key(kind, extra).map(InputEvent::KeyDown),

View File

@@ -243,14 +243,6 @@ pub fn create_endpoint() -> Option<CapSlot> {
slot_of(call0(SYS_CREATE_ENDPOINT)).ok()
}
/// Sends four words; returns 0 on success (kept for existing callers).
pub fn send(endpoint: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> usize {
match send_msg(endpoint, [w0, w1, w2, w3], None) {
Ok(()) => 0,
Err(e) => e as usize,
}
}
pub fn send_msg(endpoint: CapSlot, words: [usize; 4], cap: Option<CapSlot>) -> Result<()> {
raw(
SYS_SEND,
@@ -259,12 +251,6 @@ pub fn send_msg(endpoint: CapSlot, words: [usize; 4], cap: Option<CapSlot>) -> R
.map(|_| ())
}
/// Receives and returns just the words (kept for existing callers).
pub fn receive(endpoint: CapSlot) -> (usize, usize, usize, usize) {
let w = receive_msg(endpoint).map_or([0; 4], |r| r.words());
(w[0], w[1], w[2], w[3])
}
pub fn receive_msg(endpoint: CapSlot) -> Result<Received> {
raw(SYS_RECEIVE, [endpoint.value() as usize, 0, 0, 0, 0, 0]).and_then(Received::decode)
}
@@ -278,6 +264,16 @@ pub fn call(endpoint: CapSlot, words: [usize; 4], cap: Option<CapSlot>) -> Resul
.and_then(Received::decode)
}
/// Calls a server with four words and returns its reply's words. Needs
/// only Execute on the endpoint; the reply comes back through the
/// kernel's reply slot, so it can never reach another client.
pub fn request(endpoint: CapSlot, words: [usize; 4]) -> Result<[usize; 4]> {
match call(endpoint, words, None)? {
Received::Signal { .. } => Err(Error::InvalidArgument),
reply => Ok(reply.words()),
}
}
/// Answers the last `Call` this thread received.
pub fn reply(words: [usize; 4], cap: Option<CapSlot>) -> Result<()> {
raw(SYS_REPLY, message_regs(0, words, cap)).map(|_| ())