From 0ad655f4be8559c166c1caab627ab2fb5594ef41 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 7 Oct 2013 16:01:03 +0200 Subject: [PATCH] hw: return error code on IPC replies ref #899 --- base-hw/include/base/native_types.h | 29 ++++++++++++++++++++++++++-- base-hw/include/kernel/syscalls.h | 17 +++++++++------- base-hw/src/base/ipc.cc | 22 +++++++++++++++++++-- base-hw/src/core/kernel/ipc_node.h | 21 +++++++++++--------- base-hw/src/core/kernel/thread.h | 30 +++++++++++++++++++++-------- 5 files changed, 91 insertions(+), 28 deletions(-) diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index 45011ad492..cbdf482eb0 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -94,14 +94,39 @@ namespace Genode char payload[1<buf, utcb->base(), size); } +/** + * Copy message payload with integrated size toion message buffer + * + * This function pioneers IPC messages with headers and will + * replace utcb_to_msgbuf sometime. + */ +static void sized_utcb_to_msgbuf(Msgbuf_base * const msgbuf) +{ + Native_utcb * const utcb = Thread_base::myself()->utcb(); + size_t msg_size = utcb->ipc_msg_size(); + if (msg_size > utcb->max_ipc_msg_size()) { + kernel_log() << "oversized IPC message\n"; + msg_size = utcb->max_ipc_msg_size(); + } + memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size); +} + /** * Copy message payload to the UTCB @@ -120,8 +137,9 @@ void Ipc_client::_call() /* send request and receive reply */ msgbuf_to_utcb(_snd_msg, _write_offset, Ipc_ostream::_dst.local_name()); - size_t const s = request_and_wait(Ipc_ostream::_dst.dst(), _write_offset); - utcb_to_msgbuf(_rcv_msg, s); + int error = request_and_wait(Ipc_ostream::_dst.dst(), _write_offset); + if (error) { throw Blocking_canceled(); } + sized_utcb_to_msgbuf(_rcv_msg); /* reset unmarshaller */ _write_offset = _read_offset = RPC_OBJECT_ID_SIZE; diff --git a/base-hw/src/core/kernel/ipc_node.h b/base-hw/src/core/kernel/ipc_node.h index 1281e561bb..20b110b0df 100644 --- a/base-hw/src/core/kernel/ipc_node.h +++ b/base-hw/src/core/kernel/ipc_node.h @@ -102,7 +102,7 @@ class Kernel::Ipc_node /* update state */ if (_state != PREPARE_AND_AWAIT_REPLY) { _state = INACTIVE; } else { _state = PREPARE_REPLY; } - _await_ipc_succeeded(_inbuf.size); + _await_ipc_succeeded(1, _inbuf.size); } /** @@ -113,7 +113,7 @@ class Kernel::Ipc_node /* directly receive request if we've awaited it */ if (_state == AWAIT_REQUEST) { _receive_request(r); - _await_ipc_succeeded(_inbuf.size); + _await_ipc_succeeded(0, _inbuf.size); return; } /* cannot receive yet, so queue request */ @@ -175,7 +175,7 @@ class Kernel::Ipc_node _outbuf_dst = 0; if (!_inbuf.src) { _state = INACTIVE; } else { _state = PREPARE_REPLY; } - _await_ipc_failed(); + _await_ipc_failed(1); } } @@ -192,14 +192,17 @@ class Kernel::Ipc_node /** * IPC node returned from waiting due to message receipt * - * \param s size of incoming message + * \param s size of incoming message + * \param reply wether the received message is a reply */ - virtual void _await_ipc_succeeded(size_t const s) = 0; + virtual void _await_ipc_succeeded(bool const reply, size_t const s) = 0; /** * IPC node returned from waiting due to cancellation + * + * \param reply wether the received message is a reply */ - virtual void _await_ipc_failed() = 0; + virtual void _await_ipc_failed(bool const reply) = 0; public: @@ -316,16 +319,16 @@ class Kernel::Ipc_node case AWAIT_REPLY: _cancel_outbuf_request(); _state = INACTIVE; - _await_ipc_failed(); + _await_ipc_failed(1); return; case AWAIT_REQUEST: _state = INACTIVE; - _await_ipc_failed(); + _await_ipc_failed(0); return; case PREPARE_AND_AWAIT_REPLY: _cancel_outbuf_request(); _state = PREPARE_REPLY; - _await_ipc_failed(); + _await_ipc_failed(1); return; default: return; } diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index 76b55e6961..04721fd959 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -226,12 +226,19 @@ class Kernel::Thread } } - void _await_ipc_succeeded(size_t const s) + void _await_ipc_succeeded(bool const reply, size_t const s) { switch (_state) { case AWAIT_IPC: - _schedule(); - user_arg_0(s); + /* FIXME: return error codes on all IPC transfers */ + if (reply) { + phys_utcb()->ipc_msg_size(s); + user_arg_0(0); + _schedule(); + } else { + user_arg_0(s); + _schedule(); + } return; case AWAIT_PAGER_IPC: _schedule(); @@ -246,12 +253,18 @@ class Kernel::Thread } } - void _await_ipc_failed() + void _await_ipc_failed(bool const reply) { switch (_state) { case AWAIT_IPC: - PERR("failed to receive IPC"); - stop(); + /* FIXME: return error codes on all IPC transfers */ + if (reply) { + user_arg_0(-1); + _schedule(); + } else { + PERR("failed to receive IPC"); + stop(); + } return; case SCHEDULED: PERR("failed to receive IPC"); @@ -429,8 +442,9 @@ class Kernel::Thread void request_and_wait(Thread * const dest, size_t const size) { Ipc_node::send_request_await_reply( - dest, phys_utcb()->base(), size, phys_utcb()->base(), - phys_utcb()->size()); + dest, phys_utcb()->base(), size, + phys_utcb()->ipc_msg_base(), + phys_utcb()->max_ipc_msg_size()); } /**