From 96bbca6191139333449552c56b5d9a5b51f7f727 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 17 Oct 2013 13:51:17 +0200 Subject: [PATCH] hw: send reply size & receive request size by UTCB ref #874 --- base-hw/include/kernel/syscalls.h | 28 ++++++---- base-hw/src/base/ipc.cc | 85 ++++++++++-------------------- base-hw/src/base/pager.cc | 33 ++++++++---- base-hw/src/core/kernel/ipc_node.h | 21 ++++---- base-hw/src/core/kernel/thread.cc | 44 +++++++--------- base-hw/src/core/kernel/thread.h | 4 +- 6 files changed, 101 insertions(+), 114 deletions(-) diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index 2198dde0f4..064aa137cb 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -341,7 +341,7 @@ namespace Kernel * \retval -1 failed * * If the call returns successful the callers UTCB provides - * a valid reply message and its size. + * a valid reply message and its metadata. */ inline int request_and_wait(unsigned const id) { @@ -352,23 +352,33 @@ namespace Kernel /** * Wait for next IPC request, discard current request * - * \return size of received request (beginning with the callers UTCB base) + * \retval 0 succeeded + * \retval -1 failed + * + * If the call returns successful the callers UTCB provides + * a valid request message and its metadata. */ - inline size_t wait_for_request() { - return (size_t)syscall(WAIT_FOR_REQUEST); } + inline int wait_for_request() + { + return (int)syscall(WAIT_FOR_REQUEST); + } /** * Reply to last IPC request * - * \param size reply size (beginning with the callers UTCB base) * \param await_request if the call shall await and fetch next request * - * \return request size (beginning with the callers UTCB base) - * if await_request was set + * \retval 0 succeeded + * \retval -1 failed to receive request + * + * If await_request = 1 and the call returns successful the callers UTCB + * provides a valid request message and its metadata. */ - inline size_t reply(size_t const size, bool const await_request) { - return (size_t)syscall(REPLY, size, await_request); } + inline int reply(bool const await_request) + { + return (int)syscall(REPLY, await_request); + } /** diff --git a/base-hw/src/base/ipc.cc b/base-hw/src/base/ipc.cc index 7a8df59470..06d66f7df6 100644 --- a/base-hw/src/base/ipc.cc +++ b/base-hw/src/base/ipc.cc @@ -38,68 +38,25 @@ enum ***************/ /** - * Limit message size to the size of UTCB and message buffer + * Copy message from the callers UTCB to message buffer */ -void limit_msg_size(Msgbuf_base * const msgbuf, Native_utcb * const utcb, - size_t & size) -{ - if (size > utcb->size() || size > msgbuf->size()) { - kernel_log() << __PRETTY_FUNCTION__ << ": truncate message\n"; - size = utcb->size() < msgbuf->size() ? utcb->size() : msgbuf->size(); - } -} - - -/** - * Copy message payload to message buffer - */ -static void utcb_to_msgbuf(Msgbuf_base * const msgbuf, size_t size) -{ - Native_utcb * const utcb = Thread_base::myself()->utcb(); - limit_msg_size(msgbuf, utcb, size); - memcpy(msgbuf->buf, utcb->base(), size); -} - -/** - * Copy message payload with size header to 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) +static void 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()) { + if (msg_size > msgbuf->size()) { kernel_log() << "oversized IPC message\n"; - msg_size = utcb->max_ipc_msg_size(); + msg_size = msgbuf->size(); } memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size); } /** - * Copy message payload to the UTCB + * Copy message from message buffer to the callers UTCB */ -static void msgbuf_to_utcb(Msgbuf_base * const msgbuf, size_t size, +static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size, unsigned const local_name) -{ - Native_utcb * const utcb = Thread_base::myself()->utcb(); - *(unsigned *)utcb->base() = local_name; - size += sizeof(local_name); - limit_msg_size(msgbuf, utcb, size); - memcpy((unsigned *)utcb->base() + 1, (unsigned *)msgbuf->buf + 1, size); -} - - -/** - * Copy message payload with size header to the UTCB - * - * This function pioneers IPC messages with headers and will - * replace msgbuf_to_utcb sometime. - */ -static void msgbuf_to_sized_utcb(Msgbuf_base * const msg_buf, size_t msg_size, - unsigned const local_name) { Native_utcb * const utcb = Thread_base::myself()->utcb(); enum { NAME_SIZE = sizeof(local_name) }; @@ -161,10 +118,10 @@ void Ipc_client::_call() /* send request and receive reply */ unsigned const local_name = Ipc_ostream::_dst.local_name(); - msgbuf_to_sized_utcb(_snd_msg, _write_offset, local_name); + msgbuf_to_utcb(_snd_msg, _write_offset, local_name); int error = request_and_wait(Ipc_ostream::_dst.dst()); if (error) { throw Blocking_canceled(); } - sized_utcb_to_msgbuf(_rcv_msg); + utcb_to_msgbuf(_rcv_msg); /* reset unmarshaller */ _write_offset = _read_offset = RPC_OBJECT_ID_SIZE; @@ -204,14 +161,23 @@ void Ipc_server::_prepare_next_reply_wait() void Ipc_server::_wait() { /* receive next request */ - utcb_to_msgbuf(_rcv_msg, Kernel::wait_for_request()); - + int const error = Kernel::wait_for_request(); + if (!error) { utcb_to_msgbuf(_rcv_msg); } + else { + PERR("failed to receive request"); + throw Blocking_canceled(); + } /* update server state */ _prepare_next_reply_wait(); } -void Ipc_server::_reply() { Kernel::reply(_write_offset, 0); } +void Ipc_server::_reply() +{ + Native_utcb * const utcb = Thread_base::myself()->utcb(); + utcb->ipc_msg_size(_write_offset); + Kernel::reply(0); +} void Ipc_server::_reply_wait() @@ -223,9 +189,14 @@ void Ipc_server::_reply_wait() return; } /* send reply and receive next request */ - msgbuf_to_utcb(_snd_msg, _write_offset, Ipc_ostream::_dst.local_name()); - utcb_to_msgbuf(_rcv_msg, Kernel::reply(_write_offset, 1)); - + unsigned const local_name = Ipc_ostream::_dst.local_name(); + msgbuf_to_utcb(_snd_msg, _write_offset, local_name); + int const error = Kernel::reply(1); + if (!error) { utcb_to_msgbuf(_rcv_msg); } + else { + PERR("failed to receive request"); + throw Blocking_canceled(); + } /* update server state */ _prepare_next_reply_wait(); } diff --git a/base-hw/src/base/pager.cc b/base-hw/src/base/pager.cc index 69d1f2de31..1d31b71061 100644 --- a/base-hw/src/base/pager.cc +++ b/base-hw/src/base/pager.cc @@ -95,17 +95,24 @@ Pager_capability Pager_entrypoint::manage(Pager_object * const o) void Ipc_pager::wait_for_first_fault() { - /* receive message */ - size_t const s = Kernel::wait_for_request(); - _wait_for_fault(s); + while (Kernel::wait_for_request()) { PERR("failed to receive fault"); } + Native_utcb * const utcb = Thread_base::myself()->utcb(); + _wait_for_fault(utcb->ipc_msg_size()); } void Ipc_pager::wait_for_fault() { - /* receive first message */ - size_t const s = Kernel::reply(0, 1); - _wait_for_fault(s); + Native_utcb * const utcb = Thread_base::myself()->utcb(); + utcb->ipc_msg_size(0); + int err = Kernel::reply(1); + if (err) { + PERR("failed to receive fault"); + while (Kernel::wait_for_request()) { + PERR("failed to receive fault"); + } + } + _wait_for_fault(utcb->ipc_msg_size()); } @@ -122,7 +129,7 @@ void Ipc_pager::_wait_for_fault(size_t s) /* message is a pagefault */ Native_utcb * const utcb = Thread_base::myself()->utcb(); - Pagefault * const pf = (Pagefault *)utcb; + Pagefault * const pf = (Pagefault *)utcb->ipc_msg_base(); if (pf->valid()) { /* give our caller the chance to handle the fault */ @@ -140,11 +147,19 @@ void Ipc_pager::_wait_for_fault(size_t s) /* message is a release request from a RM session */ Native_utcb * const utcb = Thread_base::myself()->utcb(); - Pagefault_resolved * const msg = (Pagefault_resolved *)utcb; + void * const msg_base = utcb->ipc_msg_base(); + Pagefault_resolved * const msg = (Pagefault_resolved *)msg_base; /* resume faulter, send ack to RM and get the next message */ Kernel::resume_thread(msg->pager_object->badge()); - s = Kernel::reply(0, 1); + utcb->ipc_msg_size(0); + if (Kernel::reply(1)) { + PERR("failed to receive fault"); + while (Kernel::wait_for_request()) { + PERR("failed to receive fault"); + } + } + s = utcb->ipc_msg_size(); continue; } default: { diff --git a/base-hw/src/core/kernel/ipc_node.h b/base-hw/src/core/kernel/ipc_node.h index 20b110b0df..1281e561bb 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(1, _inbuf.size); + _await_ipc_succeeded(_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(0, _inbuf.size); + _await_ipc_succeeded(_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(1); + _await_ipc_failed(); } } @@ -192,17 +192,14 @@ class Kernel::Ipc_node /** * IPC node returned from waiting due to message receipt * - * \param s size of incoming message - * \param reply wether the received message is a reply + * \param s size of incoming message */ - virtual void _await_ipc_succeeded(bool const reply, size_t const s) = 0; + virtual void _await_ipc_succeeded(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(bool const reply) = 0; + virtual void _await_ipc_failed() = 0; public: @@ -319,16 +316,16 @@ class Kernel::Ipc_node case AWAIT_REPLY: _cancel_outbuf_request(); _state = INACTIVE; - _await_ipc_failed(1); + _await_ipc_failed(); return; case AWAIT_REQUEST: _state = INACTIVE; - _await_ipc_failed(0); + _await_ipc_failed(); return; case PREPARE_AND_AWAIT_REPLY: _cancel_outbuf_request(); _state = PREPARE_REPLY; - _await_ipc_failed(1); + _await_ipc_failed(); return; default: return; } diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index 2f5d544c9a..3a2d6124e5 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -90,7 +90,8 @@ void Thread::_received_ipc_request(size_t const s) { switch (_state) { case SCHEDULED: - user_arg_0(s); + _phys_utcb->ipc_msg_size(s); + user_arg_0(0); return; default: PERR("wrong thread state to receive IPC"); @@ -116,19 +117,13 @@ void Thread::_await_ipc() } -void Thread::_await_ipc_succeeded(bool const reply, size_t const s) +void Thread::_await_ipc_succeeded(size_t const s) { switch (_state) { case AWAITS_IPC: - /* 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(); - } + _phys_utcb->ipc_msg_size(s); + user_arg_0(0); + _schedule(); return; case AWAITS_PAGER_IPC: _schedule(); @@ -144,18 +139,12 @@ void Thread::_await_ipc_succeeded(bool const reply, size_t const s) } -void Thread::_await_ipc_failed(bool const reply) +void Thread::_await_ipc_failed() { switch (_state) { case AWAITS_IPC: - /* FIXME: return error codes on all IPC transfers */ - if (reply) { - user_arg_0(-1); - _schedule(); - } else { - PERR("failed to receive IPC"); - _stop(); - } + user_arg_0(-1); + _schedule(); return; case SCHEDULED: PERR("failed to receive IPC"); @@ -615,7 +604,9 @@ void Thread::_syscall_get_thread() */ void Thread::_syscall_wait_for_request() { - Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size()); + void * const buf_base = _phys_utcb->ipc_msg_base(); + size_t const buf_size = _phys_utcb->max_ipc_msg_size(); + Ipc_node::await_request(buf_base, buf_size); } @@ -641,12 +632,15 @@ void Thread::_syscall_request_and_wait() */ void Thread::_syscall_reply() { - size_t const msg_size = user_arg_1(); - bool const await_request = user_arg_2(); + bool const await_request = user_arg_1(); + void * const msg_base = _phys_utcb->ipc_msg_base(); + size_t const msg_size = _phys_utcb->ipc_msg_size(); + Ipc_node::send_reply(msg_base, msg_size); - Ipc_node::send_reply(_phys_utcb->base(), msg_size); if (await_request) { - Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size()); + void * const buf_base = _phys_utcb->ipc_msg_base(); + size_t const buf_size = _phys_utcb->max_ipc_msg_size(); + Ipc_node::await_request(buf_base, buf_size); } else { user_arg_0(0); } } diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index bb054d7ee6..087d4a8632 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -209,8 +209,8 @@ class Kernel::Thread void _received_ipc_request(size_t const s); void _await_ipc(); - void _await_ipc_succeeded(bool const reply, size_t const s); - void _await_ipc_failed(bool const reply); + void _await_ipc_succeeded(size_t const s); + void _await_ipc_failed(); /***************