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:
@@ -10,8 +10,9 @@ use libkos::syscall;
|
|||||||
extern "C" fn main() {
|
extern "C" fn main() {
|
||||||
let ep = CapSlot::const_new(0);
|
let ep = CapSlot::const_new(0);
|
||||||
|
|
||||||
let (w0, w1, w2, w3) = syscall::receive(ep);
|
if let Ok(syscall::Received::Call { words: [w0, w1, w2, w3], .. }) = syscall::receive_msg(ep) {
|
||||||
syscall::send(ep, w0.wrapping_add(1), w1, w2, w3);
|
let _ = syscall::reply([w0.wrapping_add(1), w1, w2, w3], None);
|
||||||
|
}
|
||||||
|
|
||||||
syscall::exit();
|
syscall::exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ const TICK_DELAY: u64 = 5_000_000;
|
|||||||
const MAX_RENDER_CMDS: usize = 140;
|
const MAX_RENDER_CMDS: usize = 140;
|
||||||
|
|
||||||
fn display_send(req: &DisplayRequest) {
|
fn display_send(req: &DisplayRequest) {
|
||||||
let words = req.encode();
|
let _ = syscall::request(DISPLAY_EP, req.encode());
|
||||||
syscall::send(DISPLAY_EP, words[0], words[1], words[2], words[3]);
|
|
||||||
syscall::receive(DISPLAY_EP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_rect(x: u16, y: u16, w: u16, h: u16, color: u32) {
|
fn draw_rect(x: u16, y: u16, w: u16, h: u16, color: u32) {
|
||||||
@@ -67,8 +65,9 @@ extern "C" fn main() {
|
|||||||
fn handle_input(snake: &mut Snake) {
|
fn handle_input(snake: &mut Snake) {
|
||||||
// Drain all pending events, apply the latest direction
|
// Drain all pending events, apply the latest direction
|
||||||
loop {
|
loop {
|
||||||
let _ = syscall::send(INPUT_EP, 0, 0, 0, 0);
|
let Ok([tag, kind, _, _]) = syscall::request(INPUT_EP, [0; 4]) else {
|
||||||
let (tag, kind, _, _) = syscall::receive(INPUT_EP);
|
break;
|
||||||
|
};
|
||||||
if tag == 0 { break; } // NoEvent — queue drained
|
if tag == 0 { break; } // NoEvent — queue drained
|
||||||
if tag == 1 {
|
if tag == 1 {
|
||||||
match kind {
|
match kind {
|
||||||
|
|||||||
@@ -14,25 +14,23 @@ extern "C" fn main() {
|
|||||||
} else {
|
} else {
|
||||||
run_mock(ep);
|
run_mock(ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn run_virtio(mut fb: driver_framebuffer_virtio::VirtioFramebuffer, ep: CapSlot) {
|
fn run_virtio(mut fb: driver_framebuffer_virtio::VirtioFramebuffer, ep: CapSlot) -> ! {
|
||||||
use port_framebuffer::Framebuffer;
|
use port_framebuffer::Framebuffer;
|
||||||
fb.clear(types::display::Color::rgb(30, 30, 60));
|
fb.clear(types::display::Color::rgb(30, 30, 60));
|
||||||
fb.flush();
|
fb.flush();
|
||||||
let mut srv = display_server::server::DisplayServer::new(fb);
|
let mut srv = display_server::server::DisplayServer::new(fb);
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn run_mock(ep: CapSlot) {
|
fn run_mock(ep: CapSlot) -> ! {
|
||||||
let fb = driver_framebuffer_mock::MockFramebuffer::new(
|
let fb = driver_framebuffer_mock::MockFramebuffer::new(
|
||||||
types::display::Dimension::new(640),
|
types::display::Dimension::new(640),
|
||||||
types::display::Dimension::new(480),
|
types::display::Dimension::new(480),
|
||||||
);
|
);
|
||||||
let mut srv = display_server::server::DisplayServer::new(fb);
|
let mut srv = display_server::server::DisplayServer::new(fb);
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,19 +14,17 @@ extern "C" fn main() {
|
|||||||
} else {
|
} else {
|
||||||
run_uart(ep);
|
run_uart(ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn run_input(device: driver_input_virtio::VirtioInputDevice, ep: CapSlot) {
|
fn run_input(device: driver_input_virtio::VirtioInputDevice, ep: CapSlot) -> ! {
|
||||||
let mut srv = input_server::server::InputServer::new(device);
|
let mut srv = input_server::server::InputServer::new(device);
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn run_uart(ep: CapSlot) {
|
fn run_uart(ep: CapSlot) -> ! {
|
||||||
let device = driver_input_uart::UartInputDevice::new();
|
let device = driver_input_uart::UartInputDevice::new();
|
||||||
let mut srv = input_server::server::InputServer::new(device);
|
let mut srv = input_server::server::InputServer::new(device);
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ fn request_file(shared_buf: *mut u8, filename: &[u8]) -> usize {
|
|||||||
core::ptr::write_volatile(shared_buf.add(i), b);
|
core::ptr::write_volatile(shared_buf.add(i), b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syscall::send(STORAGE_EP, CMD_READ_FILE, filename.len(), 0, 0);
|
syscall::request(STORAGE_EP, [CMD_READ_FILE, filename.len(), 0, 0]).map_or(0, |r| r[0])
|
||||||
let (file_size, _, _, _) = syscall::receive(STORAGE_EP);
|
|
||||||
file_size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoadedProcess {
|
struct LoadedProcess {
|
||||||
@@ -137,8 +135,11 @@ pub fn run(shared_buf_va: usize) -> ! {
|
|||||||
|
|
||||||
libkos::print!("init: loading snake... ");
|
libkos::print!("init: loading snake... ");
|
||||||
if let Some(snake) = load_binary(shared_buf, b"snake.elf") {
|
if let Some(snake) = load_binary(shared_buf, b"snake.elf") {
|
||||||
syscall::delegate(INPUT_EP, snake.process_cap, ipc_perms);
|
// A client only calls: Execute, never Read, so it cannot pose as
|
||||||
syscall::delegate(DISPLAY_EP, snake.process_cap, ipc_perms);
|
// the server and take other clients' requests.
|
||||||
|
let client = PermissionSet::empty().with(Permission::Execute);
|
||||||
|
syscall::delegate(INPUT_EP, snake.process_cap, client);
|
||||||
|
syscall::delegate(DISPLAY_EP, snake.process_cap, client);
|
||||||
syscall::spawn_thread_in(snake.process_cap, snake.entry_point, USER_STACK_TOP);
|
syscall::spawn_thread_in(snake.process_cap, snake.entry_point, USER_STACK_TOP);
|
||||||
libkos::println!("ok");
|
libkos::println!("ok");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ use crate::syscall;
|
|||||||
use types::bounded::CapSlot;
|
use types::bounded::CapSlot;
|
||||||
use types::display::{Color, Dimension, ScreenCoord};
|
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) {
|
fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) {
|
||||||
syscall::send(ep, w0, w1, w2, w3);
|
let r = syscall::request(ep, [w0, w1, w2, w3]).unwrap_or([usize::MAX, 0, 0, 0]);
|
||||||
syscall::receive(ep)
|
(r[0], r[1], r[2], r[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_rect(
|
pub fn draw_rect(
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ fn pack_path(path: &[u8]) -> (usize, usize) {
|
|||||||
(usize::from_le_bytes(w0), usize::from_le_bytes(w1))
|
(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) {
|
fn ipc(ep: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> (usize, usize, usize, usize) {
|
||||||
syscall::send(ep, w0, w1, w2, w3);
|
let r = syscall::request(ep, [w0, w1, w2, w3]).unwrap_or([usize::MAX, 0, 0, 0]);
|
||||||
syscall::receive(ep)
|
(r[0], r[1], r[2], r[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(ep: CapSlot, path: &[u8]) -> Option<FileHandle> {
|
pub fn open(ep: CapSlot, path: &[u8]) -> Option<FileHandle> {
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ fn decode_key(kind: usize, extra: usize) -> Option<Key> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_event(ep: CapSlot) -> Option<InputEvent> {
|
pub fn poll_event(ep: CapSlot) -> Option<InputEvent> {
|
||||||
syscall::send(ep, 0, 0, 0, 0);
|
let [tag, kind, extra, _] = syscall::request(ep, [0; 4]).ok()?;
|
||||||
let (tag, kind, extra, _) = syscall::receive(ep);
|
|
||||||
match tag {
|
match tag {
|
||||||
0 => None,
|
0 => None,
|
||||||
1 => decode_key(kind, extra).map(InputEvent::KeyDown),
|
1 => decode_key(kind, extra).map(InputEvent::KeyDown),
|
||||||
|
|||||||
@@ -243,14 +243,6 @@ pub fn create_endpoint() -> Option<CapSlot> {
|
|||||||
slot_of(call0(SYS_CREATE_ENDPOINT)).ok()
|
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<()> {
|
pub fn send_msg(endpoint: CapSlot, words: [usize; 4], cap: Option<CapSlot>) -> Result<()> {
|
||||||
raw(
|
raw(
|
||||||
SYS_SEND,
|
SYS_SEND,
|
||||||
@@ -259,12 +251,6 @@ pub fn send_msg(endpoint: CapSlot, words: [usize; 4], cap: Option<CapSlot>) -> R
|
|||||||
.map(|_| ())
|
.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> {
|
pub fn receive_msg(endpoint: CapSlot) -> Result<Received> {
|
||||||
raw(SYS_RECEIVE, [endpoint.value() as usize, 0, 0, 0, 0, 0]).and_then(Received::decode)
|
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)
|
.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.
|
/// Answers the last `Call` this thread received.
|
||||||
pub fn reply(words: [usize; 4], cap: Option<CapSlot>) -> Result<()> {
|
pub fn reply(words: [usize; 4], cap: Option<CapSlot>) -> Result<()> {
|
||||||
raw(SYS_REPLY, message_regs(0, words, cap)).map(|_| ())
|
raw(SYS_REPLY, message_regs(0, words, cap)).map(|_| ())
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
use types::bounded::CapSlot;
|
|
||||||
|
|
||||||
pub async fn send(endpoint: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> usize {
|
|
||||||
libkos::syscall::send(endpoint, w0, w1, w2, w3)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn receive(endpoint: CapSlot) -> (usize, usize, usize, usize) {
|
|
||||||
libkos::syscall::receive(endpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn wait_for_interrupt(_irq: CapSlot) {
|
|
||||||
libkos::syscall::yield_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn acknowledge_interrupt(_irq: CapSlot) {
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub mod async_syscall;
|
|
||||||
pub mod codec;
|
pub mod codec;
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod select;
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
pub use codec::{Decode, Encode};
|
pub use codec::{Decode, Encode};
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
#[macro_export]
|
|
||||||
macro_rules! select {
|
|
||||||
(
|
|
||||||
$msg:ident = receive($ep:expr) => $ipc_body:block
|
|
||||||
$irq:ident = wait_interrupt($irq_cap:expr) => $irq_body:block
|
|
||||||
) => {
|
|
||||||
{
|
|
||||||
let sources = types::syscall_abi::SYS_WAIT_ANY;
|
|
||||||
let wake = libkos::syscall::receive($ep as usize);
|
|
||||||
let $msg = wake;
|
|
||||||
$ipc_body
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -4,24 +4,52 @@ mod tests;
|
|||||||
use crate::codec::{Decode, Encode};
|
use crate::codec::{Decode, Encode};
|
||||||
use types::bounded::CapSlot;
|
use types::bounded::CapSlot;
|
||||||
|
|
||||||
|
/// The reply to a request that does not decode. No protocol uses this
|
||||||
|
/// tag, so every client decodes it as an error.
|
||||||
|
pub const MALFORMED: usize = usize::MAX;
|
||||||
|
|
||||||
pub trait Server {
|
pub trait Server {
|
||||||
type Request: Decode;
|
type Request: Decode;
|
||||||
type Response: Encode;
|
type Response: Encode;
|
||||||
|
|
||||||
fn handle(&mut self, request: Self::Request) -> Self::Response;
|
fn handle(&mut self, request: Self::Request) -> Self::Response;
|
||||||
|
|
||||||
fn run(&mut self, endpoint: CapSlot) {
|
/// Serves `endpoint` until receiving on it fails (it was destroyed or
|
||||||
|
/// the capability revoked), then returns why. Every `Call` gets a
|
||||||
|
/// reply, `[MALFORMED, ..]` if it does not decode; a one-way `Send` is
|
||||||
|
/// handled without one; notification signals are ignored.
|
||||||
|
fn run(&mut self, endpoint: CapSlot) -> libkos::syscall::Error {
|
||||||
|
use libkos::syscall::{Received, receive_msg, reply_recv};
|
||||||
|
let mut next = receive_msg(endpoint);
|
||||||
loop {
|
loop {
|
||||||
let words = libkos::syscall::receive(endpoint);
|
let message = match next {
|
||||||
if let Some(request) = Self::Request::decode([words.0, words.1, words.2, words.3]) {
|
Ok(m) => m,
|
||||||
let response = self.handle(request);
|
Err(e) => return e,
|
||||||
let encoded = response.encode();
|
};
|
||||||
libkos::syscall::send(endpoint, encoded[0], encoded[1], encoded[2], encoded[3]);
|
next = match message {
|
||||||
|
Received::Call { words, .. } => {
|
||||||
|
let reply = match Self::Request::decode(words) {
|
||||||
|
Some(request) => self.handle(request).encode(),
|
||||||
|
None => [MALFORMED, 0, 0, 0],
|
||||||
|
};
|
||||||
|
reply_recv(endpoint, reply, None)
|
||||||
}
|
}
|
||||||
|
Received::Message { words, .. } => {
|
||||||
|
if let Some(request) = Self::Request::decode(words) {
|
||||||
|
let _ = self.handle(request);
|
||||||
|
}
|
||||||
|
receive_msg(endpoint)
|
||||||
|
}
|
||||||
|
Received::Signal { .. } => receive_msg(endpoint),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve<S: Server>(server: &mut S, endpoint: CapSlot) {
|
/// Runs `server` on `endpoint` for good. A server whose endpoint is gone
|
||||||
server.run(endpoint);
|
/// has nobody left to serve, so it says why and exits.
|
||||||
|
pub fn serve<S: Server>(server: &mut S, endpoint: CapSlot) -> ! {
|
||||||
|
let error = server.run(endpoint);
|
||||||
|
libkos::println!("server: endpoint {} unusable ({:?}), exiting", endpoint.value(), error);
|
||||||
|
libkos::syscall::exit()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,5 @@ pub fn run() -> ! {
|
|||||||
|
|
||||||
let mut srv = server::InputServer::new(device);
|
let mut srv = server::InputServer::new(device);
|
||||||
let ep = types::bounded::CapSlot::new(0).unwrap();
|
let ep = types::bounded::CapSlot::new(0).unwrap();
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,5 @@ mod tests;
|
|||||||
pub fn run() -> ! {
|
pub fn run() -> ! {
|
||||||
let mut srv = server::LogServer::new();
|
let mut srv = server::LogServer::new();
|
||||||
let ep = types::bounded::CapSlot::new(0).unwrap();
|
let ep = types::bounded::CapSlot::new(0).unwrap();
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,5 @@ mod tests;
|
|||||||
pub fn run() -> ! {
|
pub fn run() -> ! {
|
||||||
let mut srv = server::PermissionManager::new();
|
let mut srv = server::PermissionManager::new();
|
||||||
let ep = types::bounded::CapSlot::new(0).unwrap();
|
let ep = types::bounded::CapSlot::new(0).unwrap();
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,5 @@ pub fn run() -> ! {
|
|||||||
let mut srv = server::SessionServer::new(create_cap);
|
let mut srv = server::SessionServer::new(create_cap);
|
||||||
srv.register_app("snake", "/apps/snake.elf");
|
srv.register_app("snake", "/apps/snake.elf");
|
||||||
let ep = types::bounded::CapSlot::new(0).unwrap();
|
let ep = types::bounded::CapSlot::new(0).unwrap();
|
||||||
server_framework::serve(&mut srv, ep);
|
server_framework::serve(&mut srv, ep)
|
||||||
loop { libkos::syscall::yield_now(); }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,17 @@ pub fn run() -> ! {
|
|||||||
|
|
||||||
let ep = types::bounded::CapSlot::new(0).unwrap();
|
let ep = types::bounded::CapSlot::new(0).unwrap();
|
||||||
|
|
||||||
|
let mut next = syscall::receive_msg(ep);
|
||||||
loop {
|
loop {
|
||||||
let (w0, w1, _w2, _w3) = syscall::receive(ep);
|
let message = match next {
|
||||||
|
Ok(m) => m,
|
||||||
match w0 {
|
Err(e) => {
|
||||||
|
libkos::println!("storage: endpoint unusable ({:?}), exiting", e);
|
||||||
|
syscall::exit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let [w0, w1, _, _] = message.words();
|
||||||
|
let reply = match w0 {
|
||||||
CMD_READ_FILE => {
|
CMD_READ_FILE => {
|
||||||
let filename_len = w1;
|
let filename_len = w1;
|
||||||
let buf = shared_buf();
|
let buf = shared_buf();
|
||||||
@@ -60,12 +67,14 @@ pub fn run() -> ! {
|
|||||||
libkos::println!("NOT FOUND");
|
libkos::println!("NOT FOUND");
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall::send(ep, file_size, 0, 0, 0);
|
[file_size, 0, 0, 0]
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
syscall::send(ep, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_ => [0, 0, 0, 0],
|
||||||
|
};
|
||||||
|
next = match message {
|
||||||
|
syscall::Received::Call { .. } => syscall::reply_recv(ep, reply, None),
|
||||||
|
_ => syscall::receive_msg(ep),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user